-1

I'm currently creating a test for a legacy code and stuck with this error message when running my test (see below):

Exception thrown at 0x0F5001EF (Control.dll) in sample.exe:
0xC0000005: Access violation reading location 0xDDDDDDDD.

I understand that 0xDDDDDDDD means code was trying to access an already deleted pointer. But what I do not understand is where it was 'prematurely' deleted.

I've kept it to the very bare minimum. Here is my code

CDevice::CDevice() 
{
    numLedRows = numLedCols = 0;
}

CDevice::~CDevice()
{
   std::cout << "destructor!" << std::endl;
}

HRESULT CDevice::Init(IDevice* control)
{
    HRESULT hr = S_OK;
    deviceCtl.reset(control);
    return hr;
}

where:

std::unique_ptr<IDevice>   deviceCtl;

And my test:

TEST_F(deviceControlTest, test2)
{
     sut_->Init(deviceMock_.get());
}

where

std::unique_ptr<CDevice> sut_;
std::unique_ptr<DeviceMock> deviceMock_;

and in SetUp...

sut_ = std::make_unique<CDevice>();
deviceMock_ = std::make_unique<DeviceMock>();

I have also tried using shared_ptr for DeviceMock, same behavior.

Is this something wrong with my code? Or is it my test?? Any suggestions will be greatly appreciated!

kzaiwo
  • 1,558
  • 1
  • 16
  • 45
  • 3
    Please include a [mcve] in the question – 463035818_is_not_an_ai May 27 '19 at 10:12
  • 1
    `0xDDDDDDDD` is one of way some compiler indicates that pointer was not initialized to specific value. – Marek R May 27 '19 at 10:15
  • 2
    Hard to tell what's going on with only snippets of code, but I see that `deviceMock_` is a `unique_ptr`, which you then pass to `Init()`, which then `reset()`s `deviceCtl` with it... so now you have *two* smart pointers, *either* of which will `delete` the pointer held when it's going out of scope. That's fishy, a pointer should only ever have *one* owner... is `deviceMock_` still in existence when the exception is thrown? – DevSolar May 27 '19 at 10:19
  • You need to make a better effort of supplying a [mcve], similar to [this](https://www.ideone.com/fTx6nA) – PaulMcKenzie May 27 '19 at 10:32
  • `.get()` is not a valid way of transferring ownership out of a `unique_ptr`. As @DevSolar points out you are violating the uniqueness precondition. – Ben Voigt May 28 '19 at 02:39
  • Thanks! I have now updated my code to use shared_ptr instead. However, I still get the same error. But if I use ```deviceCtl = control;``` instead of ```deviceCtl.reset(control);``` then the error disappears. What could be the reason for this?? – kzaiwo May 28 '19 at 03:21
  • Have you read any of the comments? We need a _complete_ example to tell exactly what happens. You say you are now using shared_ptr. If you are still using .get(), though, your code is still broken. _We can't tell, because you are only showing snippets instead of a true example._ Voting to close. – DevSolar May 28 '19 at 10:34
  • Switch your smart pointer to std::weak_ptr, or much better [boost intrusive_ptr](https://www.boost.org/doc/libs/1_60_0/libs/smart_ptr/intrusive_ptr.html) – Victor Gubin Jun 14 '19 at 07:51

1 Answers1

0

I think you have double delete issue here: both deviceMock_ and deviceCtl are handling same pointer. It is deleted twice (doeasn't matter if for unique and shared ptr) once when CDevice dtor is called and it's member, including the smart ptr used and once when deviceControlTest dtor is called. Please note that in gtest the call order is always the same for each test: test suite ctor, test suite setup, test body, test suite teardown, test suite dtor). Options:

  1. Use shared_ptr and copy it inside Init (do not reset it, just assign deviceCtl = control;).
  2. Inject via unique_ptr using approach from this SO question.
Quarra
  • 2,527
  • 1
  • 19
  • 27