Error: R6025 - pure virtual call

432 views
Skip to first unread message

sau_73

unread,
May 13, 2011, 12:51:54 PM5/13/11
to Google C++ Mocking Framework
ISSUE: Getting a Debug Error when running unit tests in 1.6 where in
1.5 it worked fine.
Error: R6025 - pure virtual call

Background:
First of all, thanks this excellent tool which has revolutionised my C+
+ unit testing!
I've been using gmock for a bout a year now, and sometimes I need to
mock COM interfaces. In 1.5 it worked out fine. I am presently
upgrading to 1.6 and now I'm getting the above error whenever the Mock
COM object is destroyed. In my real code a factory method cocreates a
COM object and assigns it to a CComPtr<>. In my unit test I override
the factory so I can inject a fake COM object.
I have a TestDouble for the COM object installed in my Testable
version of the SUT and pass back the address of that (it gets copied
into a CComPtr<>.
In v1.5 this all worked, fine, but I'm getting the runtime error in
v1.6.
The Release() call made by the CComPtr<> going out of scope for the
last time seems to be passed on to the base class (IFoo interface in
this case) rather than being handled by the TestDouble.
I've tried to debug this, but get a bit lost in the depths of the
gmock code :)

I've put together a sample project that demonstrates the problem - but
I can't see any way to attach it to this post.

Here's the code - shout if you want the full sample...
---------------------------------------------------------
class CSystemUnderTest
{
public:

void DoSomething(){
GetFoo(m_pDoc);
m_pDoc->Lookup();
}

protected:
virtual void GetFoo(CComPtr<IFoo>& pFoo) { // do nothing we're just
testing }
private:
CComPtr<IFoo> m_pDoc;
};
---------------------------------------------------------
Here's the "interface" for the depended upon COM object (you'll need
to include atlcom.h and atlase.h I think..)
---------------------------------------------------------
MIDL_INTERFACE("A5EB27A2-3F8F-44E7-AFAC-762DFE34F4CA")
IFoo : public IDispatch
{
public:
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Lookup()=0;
};
---------------------------------------------------------
Now here's my testdouble (Mock class):
---------------------------------------------------------
// Use this macro to mock the IUnknown interface
#define MOCK_IUNKNOWN MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE,
AddRef, ULONG()); \
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Release, ULONG()); \
MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, QueryInterface,
HRESULT(const IID&, void**));

// Use this macro to mock the IDispatch interface
#define MOCK_IDISPATCH MOCK_IUNKNOWN \
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTypeInfoCount,
HRESULT(UINT*)); \
MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTypeInfo,
HRESULT(UINT, LCID, ITypeInfo**)); \
MOCK_METHOD5_WITH_CALLTYPE(STDMETHODCALLTYPE, GetIDsOfNames,
HRESULT(const IID&, LPOLESTR *, UINT, LCID, DISPID*)); \
MOCK_METHOD8_WITH_CALLTYPE(STDMETHODCALLTYPE, Invoke,
HRESULT(DISPID,REFIID,LCID,WORD,
DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*));

class IFoo_TestDouble : public IFoo
{
public:
// move const/dest impl to cpp file for quicker
complile..
IFoo_TestDouble() {
ON_CALL(*this, QueryInterface(_,_))
.WillByDefault(DoAll(SetArgumentPointee<1>((void*)this),
Return(S_OK)));
}
virtual ~IFoo_TestDouble(){}

MOCK_IDISPATCH;

MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Lookup, HRESULT());
};
-----------------------------------------------
Now here's my testable CSystemUnderTest (for injecting fake IFoo)

class Testable_CSystemUnderTest : public CSystemUnderTest
{
public:
Testable_CSystemUnderTest() {}

IFoo_TestDouble& Foo(){return m_Doc;}
protected:
virtual void GetFoo(CComPtr<IFoo>& pFoo)
{
/// Assign the ptr to the testdouble. Faked IUnknown
methods will fake the COM ref counting..
pFoo = (IFoo*)&m_Doc;
}

private:
IFoo_TestDouble m_Doc;
};
--------------------------------------------------
And here's a test that produces the error:
{
Testable_CSystemUnderTest test;
test.DoSomething();
}
<- error occurs when the Testable_CSystemUnderTest goes out of scope..

Like I said, this all worked fine under gmock 1.5, so has something
changed in the internal implementation to make this break?

Thanks for you help.

Vlad Losev

unread,
May 13, 2011, 4:22:41 PM5/13/11
to sau_73, Google C++ Mocking Framework
When a Testable_CSystemUnderTest instance is destroyed, CSystemUnderTest::m_pDoc's destructor will try to call Release on its pointer. But the pointed object (m_Doc) will have already been destroyed as members' destructors are run before the base class's ones.
 
Thanks for you help.

sau_73

unread,
May 13, 2011, 4:36:38 PM5/13/11
to Google C++ Mocking Framework
Thanks for the quick reply.
And yes - that was the problem! I saw it just after I'd sent the
post :)
I guess the fact that it used to work and now it doesn't means that
whatever loophole allowed it to work before has been closed. That's
good!

Steve

On May 13, 9:22 pm, Vlad Losev <v...@losev.com> wrote:
Reply all
Reply to author
Forward
0 new messages