I'm having trouble adding a unit test for a class that I have. One of the functions uses a boost pointer (dynamic pool) and there's always a segmentation fault that occurs whenever I compile the test as seen from the backtrace. If run normally, it compiles properly but when using Google Mock it fails.
The Mock::AllowLeak also does not seem to work for me. Unfortunately, I cannot share the code in public so if anybody has experienced testing functions that uses boost pointers with Google Mock feel free to share some tips.
Thank you
Function to be tested:
RetObj* Foo::FooFunction(uint32_t param1)
{
spRetObj_t ptr = pool_storage->Get<RetObj>(); //error occurs when I use this
...
return ptr;
}
spRetObj_t initialize:
typedef stdex::IPool<RetObj>::iptr spRetObj_t;
Pool storage:
#include "stdex/dynamic_pool.hpp"
...
class PoolStorage
{
...
template<typename T>
typename stdex::IPool<T>::iptr Get(void (T::*on_free)(void) = 0);
...
}
Code in boost where the exception was thrown:
T * operator->() const
{
BOOST_ASSERT( px != 0 );
return px;
}
Related
I am trying to use TLM2 for a simulation project but for some reason I can't use b_transport the same way I see it used in other projects, here is the code snippet that doesn't build due to this error(error C2039 : 'b_transport' : is not a member of 'tlm_utils::simple_initiator_socket<Initiator,32,tlm::tlm_base_protocol_types>')
#include <systemc.h>
#include <tlm_utils/simple_target_socket.h>
#include <tlm_utils/simple_initiator_socket.h>
SC_MODULE(Memory) {
tlm_utils::simple_target_socket<Memory> targetSocket;
SC_CTOR(Memory) {
targetSocket.register_b_transport(this, &BTransportCallback);
}
void BTransportCallback(tlm::tlm_generic_payload& payload, sc_time& delay) {
// ...
}
};
SC_MODULE(Initiator) {
tlm_utils::simple_initiator_socket<Initiator> initiatorSocket;
SC_CTOR(Initiator) {
}
};
SC_MODULE(TopLevel) {
Memory* memory;
Initiator* initiator;
SC_CTOR(TopLevel) {
memory = new Memory("Memory");
initiator = new Initiator("Initiator");
initiator->initiatorSocket.bind(memory->targetSocket);
// this is just an example for build test, obviously this isn't a correct call
tlm::tlm_generic_payload p;
initiator->initiatorSocket.b_transport(p, SC_ZERO);
}
};
I know what this error implies, but I don't understand why the systemc includes with tlm2 doesn't find this method.
I use SystemC 2.3.3 (Includes TLM), and there are no issues at includes, since I can use other systemc things normally.
Please let me know if you encountered something similar or what I might've overlooked(maybe I am using the wrong headers ?).
I found the issue. I had to use the arrow (->) operator, so this is the correct usage
SC_MODULE(TopLevel) {
Memory* memory;
Initiator* initiator;
SC_CTOR(TopLevel) {
memory = new Memory("Memory");
initiator = new Initiator("Initiator");
sc_time delay = SC_ZERO_TIME;
tlm::tlm_generic_payload p;
initiator->initiatorSocket.bind(memory->targetSocket);
initiator->initiatorSocket->b_transport(p, delay);
}
};
Right now i'm busy writing an event based queue. I wanted to do some unit testing but i'm running into an error. In Microsoft Visual Studio, when making a unit test project, you have to implement this function for each type you do an assert on:
namespace Microsoft
{
namespace VisualStudio
{
namespace CppUnitTestFramework
{
template<> static std::wstring ToString<T>>(const class T& t)
{
//code goes here
}
}
}
}
the problem is that the queue is not changing the object that was passed into it. because of this i wanted to write a unit test that verified that the object pointed to in the queue, was the same address as the object outside of the queue. I wrote the test as follows:
TEST_METHOD(REGISTERED_PROCESSORS_HAVE_ACCURATE_ADDRESSES_IN_QUEUE_MANAGER)
{
QueueProcessor queue;
ActionProcessor processor;
processor.loadFromJson({ {actionProcessorProperties::QUEUE_NAME, "alpha"} });
queue.registerProcessor(&processor);
Assert::AreEqual(&processor, queue.processors["alpha"][0]);
}
i then get this error:
Test writer must define specialization of ToString<Q* q> for your class class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > __cdecl Microsoft::VisualStudio::CppUnitTestFramework::ToString<class ActionProcessor>(class ActionProcessor *).
so how do I implement ToString on a pointer? when I try putting the data type in the compiler complains. Also how do I then display the pointer as a string value?
thanks for the help.
edit:
i found the unit test works fine if you convert the pointers to uintptr_t. However the type conversion mid assert kinda messes up the readability of the code. Is there a cleaner solution?
TEST_METHOD(REGISTERED_PROCESSORS_HAVE_ACCURATE_ADDRESSES_IN_QUEUE_MANAGER)
{
QueueProcessor queue;
ActionProcessor processor;
processor.loadFromJson({ {actionProcessorProperties::QUEUE_NAME, "alpha"} });
queue.registerProcessor(&processor);
Assert::AreEqual(reinterpret_cast<uintptr_t> (&processor),
reinterpret_cast<uintptr_t>(queue.processors["alpha"][0]));
}
Since nobody seems to be answering this, I'm going to mark my edit as correct. Perhaps the way to do it is by converting the pointers to uintptr_t types. The code below fixes the issue:
TEST_METHOD(REGISTERED_PROCESSORS_HAVE_ACCURATE_ADDRESSES_IN_QUEUE_MANAGER)
{
QueueProcessor queue;
ActionProcessor processor;
processor.loadFromJson({ {actionProcessorProperties::QUEUE_NAME, "alpha"} });
queue.registerProcessor(&processor);
Assert::AreEqual(reinterpret_cast<uintptr_t> (&processor),
reinterpret_cast<uintptr_t>(queue.processors["alpha"][0]));
}
I am currently trying to wrap my head around on how to properly use C++ smart pointers. I keep reading that I should use make_unique() most of the time, but I always get segfaults with them and I am unsure on how to properly use them.
I am trying to instantiate some Protocol Buffers generated classes for testing purpose. Here's what I am trying to do:
using namespace std;
#include <catch.hpp>
class Fixtures {
public:
std::unique_ptr<DescendingMessage> getDescendingMessage();
std::unique_ptr<VehicleCommand> getVehicleCommand_Door();
std::unique_ptr<Door> getDoorCommand_open();
};
unique_ptr<DescendingMessage> Fixtures::getDescendingMessage() {
auto descendingMessage = make_unique<DescendingMessage>();
descendingMessage->set_allocated_vehicle_command(getVehicleCommand_Door().get());
return move(descendingMessage);
}
unique_ptr<VehicleCommand> Fixtures::getVehicleCommand_Door() {
auto vehicleCommand = make_unique<VehicleCommand>();
vehicleCommand->set_allocated_door_operation(getDoorCommand_open().get());
return move(vehicleCommand);
}
unique_ptr<Door> Fixtures::getDoorCommand_open() {
auto door = make_unique<Door>();
door->set_mode(Door_Mode_OPEN);
return move(door);
}
SCENARIO("Get a sample protobuf model from Fixtures and test its content") {
auto fixtures = make_unique<Fixtures>();
auto descendingMessage = fixtures->getDescendingMessage();
REQUIRE(!descendingMessage->has_metadata());
REQUIRE(!descendingMessage->has_state_request());
REQUIRE(descendingMessage->has_vehicle_command());
}
Whenever I instantiate my Fixtures class in my Catch2 Test, I get a segmentation fault when I try to get an instance of DescendingMessage. I know it has to do with memory getting freed twice, but I don't know how to properly fix this issue. I tried with shared_ptr and it does the same thing. What am I missing here? I would really like to use smart pointers but I am getting nowhere with them for now :/
You need to pass ownership of your smart pointers.
You are currently using unique_ptr::get() which only returns the raw pointer.
When passing ownership use unique_ptr::release() which returns the pointer and releases ownership.
In your code:
// object used to set vehicle command
// but object is still owned by unique_ptr
set_allocated_vehicle_command(getVehicleCommand_Door().get());
// object is used to set vehicle command
// and ownership is released from unique_ptr
set_allocated_vehicle_command(getVehicleCommand_Door().release());
I have a C++ code as follow:
tryIt.h file
class tryIt : public someOtherClass
{
public:
bool insertI ();
private:
CommandI* m_pInsertI;
bool createInsertI();
}
tryIt.cpp file
tryIt ::tryIt () : m_pInsertI(NULL)
{
createInsertI();
}
tryIt ::~tryIt ()
{
if(m_pInsertI!=NULL)
{
delete m_pInsertI;
m_pInsertI=NULL
}
}
bool createInsertI()
{
m_pInsertI = returnFromSomeOtherFunction();
return true;
}
bool insertI()
{
// Over here if I use m_pInsertI anyhow my code fails with seg fault
// even checking if(m_pInsertI==NULL) make the code throw seg fault
}
So the issue is touching m_pInsertI anywhere make my code throw Seg. fault (Signal 11). Even debugged the code with GDB but didn't got any useful info.
Compiler is GCC
Please help.
Sounds like the instance of this class does not exist or damaged.
That is why you can't access any of its members and even if(m_pInsertI==NULL) check raises the exception.
in tryIt.cpp shouldn't
bool createInsertI()
be
bool tryIt::createInsertI()
same with insertI()
I see the following two possibilities:
returnFromSomeOtherFunction() already returns a corrupted pointer
You are copying your instance using the compiler generated methods (see example below)
Example (Rule of three violation)
tryIt instance1; // allocates instance2.m_pInsertI
{
tryIt instance2;
instance1 = instance 2; // performs a shallow copy
} // here, instance2.m_pInsertI is deleted
instance1.insertI(); // access violation
Recommendation:
Whether or not this is cause your problem: Do not implement manual memory management. Simply use a std::unique_ptr<CommandI> for m_pInsertI instead, so you do not need to implement the destructor or copy constructors/operators.
I have written a few C++ classes which employ a variety C++ libraries. I made a Windows Form project, and set it up to use my classes successfully. However, I recently made another C++ class and now I consistently get:
A first chance exception of type 'System.AccessViolationException' occurred in TEST_OCU.exe
which leads to:
An unhandled exception of type 'System.TypeInitializationException' occurred in Unknown Module.
Additional information: The type initializer for '<Module>' threw an exception.
The program hasn't even started running yet, and the new, problem-causing C++ class hasn't even been constructed yet. If I comment out the new call, and only have a pointer to this new C++ class, everything compiles just fine. BUT, if somewhere I do something like:
if(new_class_ptr != NULL)
new_class_ptr->SomeFunction() //It doesn't matter what function this is
This will throw those violations again
Some facts:
Compiling and linking is fine, this seems to be a run-time problem.
My solution employs unmanaged C++ libraries and classes (that I have written), and one managed C++ Form.
So far I haven't had any problems, I've used a few C++ libraries successfully for a while. This is caused by a new C++ class I recently wrote.
The C++ class which causes these violations uses std::ifstream to read in a file. If I comment out the std::ifstream input_file(filename); my Forms project runs successfully.
If I use the C++ class in a simple Win32 project, it compiles and runs just fine with the std::ifstream.
I have a strong feeling it is related to this question
Could anyone offer any advice? Thank you
EDIT: I'm providing some parts of my form code I have. RTSPConnection works just fine, the offending class is RTPStream
public ref class Form1 : public System::Windows::Forms::Form
{
public:
// ... Lots of generated code here ...
//Calls I've written
private: static RTSPConnection * rtsp_connection_ = NULL; //This class works
private: static RTPStream * rtp_connection_ = NULL; //This class does not
bool streaming_;
System::Threading::Thread^ streaming_thread_;
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
if(rtsp_connection_ == NULL)
{
rtsp_connection_ = new RTSPConnection("rtsp://192.168.40.131:8554/smpte");
streaming_ = false;
}
//if(rtp_connection_ == NULL)
// rtp_connection_ = new RTPStream("test");
}
private: System::Void Form1_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e) {
if(rtsp_connection_ != NULL)
rtsp_connection_->StopStreaming();
}
private: System::Void button1_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) {
if(!streaming_)
{
//Start Streaming
streaming_thread_ = gcnew Thread(gcnew ThreadStart(&Form1::WorkerThreadFunc));
streaming_thread_->Start();
this->button1->Text = L"Stop Streaming";
streaming_ = true;
}
else
{
//Stop Streaming
if(rtsp_connection_ != NULL)
rtsp_connection_->StopStreaming();
//THIS CALL RIGHT HERE WILL THROW AN ACCESS VIOLATION
if(rtp_connection_ != NULL)
rtp_connection_->StopStreaming();
this->button1->Text = L"Start Streaming";
streaming_ = false;
}
}
};
These two statements appear to contradict each other:
The program hasn't even started running yet, and the new,
problem-causing C++ class hasn't even been constructed yet.
If I comment out the new call, and only have a pointer to this new C++
class, everything compiles just fine.
Q: Could you please post the code where you're calling "new"? Or are you calling "new" - perhaps you just meant "if I comment out my new class"?
Q: Could you please set a breakpoint in your constructor, look at the stack trace, and see who's invoking it? And when?
========== ADDENDUM ==========
I strongly disagree with this statement:
It all hinges on this line: std::ifstream input_file(filename);
where filename is a std::string.
I strong AGREE with this statement:
You get almost the same error in C# if you have static class members
that depend on each other and they aren't initialised in the order you
expect. In C++, if you had a static singleton and another static
member that referred to it
Calling "ifstream" isn't the problem per se. Rather, somehow invoking the class that invokes ifstream before the program has initialized is the problem.
Q: Are you calling "new" on this class? If so, where. Please cut/paste that code.
Per MSDN, you should be able to set "mixed mode debugging". I have lots of different copies of MSVS :) ... but MSVS 2010/C++ doesn't happen to be one of them. Please look at this documentation:
http://msdn.microsoft.com/en-us/library/fz5w87ad.aspx
http://msdn.microsoft.com/en-us/library/cktt23yw