I got crazy by tracking down a double free issues with CPPUtest and I could narrow down the problem. The problem seems to come when I use a reference as an output parameter, it complains about double freeing the field in the referenced object.
As always, an example is clearer than too many words:
#include <string>
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
#include <CppUTestExt/MockSupport.h>
//--------------------------------------------------------------------------------------------
class MyReference
{
public:
MyReference():
m_name("Hello")
{
}
~MyReference(){}
private:
// If I remove this field, it works as expected
std::string m_name; // Double freed!!!??
};
//--------------------------------------------------------------------------------------------
class ReturnReference
{
public:
ReturnReference(){}
virtual ~ReturnReference(){}
virtual bool returnReference(MyReference& ref)
{
ref = m_ref;
return true;
}
private:
MyReference m_ref;
};
//--------------------------------------------------------------------------------------------
class ReturnReferenceMock:
public ReturnReference
{
public:
ReturnReferenceMock(){}
~ReturnReferenceMock(){}
bool returnReference(MyReference& ref)
{
return mock().actualCall("returnReference").onObject(this).
withOutputParameter("ref", &ref).returnIntValue();
}
};
//--------------------------------------------------------------------------------------------
class UseReturnReference
{
public:
UseReturnReference(ReturnReference* returnReference) :
m_pReturnReference(returnReference)
{
}
~UseReturnReference()
{
delete m_pReturnReference;
}
void useReturnReference()
{
MyReference ref;
m_pReturnReference->returnReference(ref);
}
private:
ReturnReference* m_pReturnReference;
};
//--------------------------------------------------------------------------------------------
TEST_GROUP(TestReferenceMock)
{
TEST_SETUP()
{
// XXX: Double free!
//MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
}
TEST_TEARDOWN()
{
mock().clear();
MemoryLeakWarningPlugin::turnOnNewDeleteOverloads();
}
};
TEST(TestReferenceMock, willItFail)
{
ReturnReferenceMock* retRefMock = new ReturnReferenceMock();
UseReturnReference useRef(retRefMock);
MyReference* ref = new MyReference();
mock().expectOneCall("returnReference").onObject(retRefMock).
withOutputParameterReturning("ref", ref, sizeof(*ref)).
andReturnValue(true);
useRef.useReturnReference();
mock().checkExpectations();
// Not doing this reports a memory leak as expected!
delete ref;
}
TEST(TestReferenceMock, willItFail2)
{
ReturnReferenceMock* retRefMock = new ReturnReferenceMock();
UseReturnReference useRef(retRefMock);
MyReference ref;
mock().expectOneCall("returnReference").onObject(retRefMock).
withOutputParameterReturning("ref", &ref, sizeof(ref)).
andReturnValue(true);
useRef.useReturnReference();
mock().checkExpectations();
}
//--------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
// Run the tests
return CommandLineTestRunner::RunAllTests(argc, argv);
}
The previous snippet reports the following error:
main.cpp:112: error: Failure in TEST(TestReferenceMock, willItFail2)
willItFail2:112: error:
Deallocating non-allocated memory
allocated at file: <unknown> line: 0 size: 0 type: unknown
deallocated at file: <unknown> line: 0 type: delete
.
main.cpp:94: error: Failure in TEST(TestReferenceMock, willItFail)
willItFail:94: error:
Deallocating non-allocated memory
allocated at file: <unknown> line: 0 size: 0 type: unknown
deallocated at file: <unknown> line: 0 type: delete
.
Errors (2 failures, 2 tests, 2 ran, 6 checks, 0 ignored, 0 filtered out, 0 ms)
This seems a bug in CPPUnit to me. However, the bug might probably come from a missuse of the library, but what am I doing wrong? Is it really possible to pass a reference as output parameter?
I got crazy by tracking down a double free issues with CPPUtest and I could narrow down the problem. The problem seems to come when I use a reference as an output parameter, it complains about double freeing the field in the referenced object.
As always, an example is clearer than too many words:
The previous snippet reports the following error:
This seems a bug in CPPUnit to me. However, the bug might probably come from a missuse of the library, but what am I doing wrong? Is it really possible to pass a reference as output parameter?