eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.22k stars 170 forks source link

SIGSEGV when when mock with shared_ptr #286

Closed zhlongfj closed 1 year ago

zhlongfj commented 1 year ago

My code: auto mock1 = new Mock(); When(Method(*mock1, resId)).AlwaysReturn("1"); auto meta = shared_ptr(&mock1->get());

error info: FATAL ERROR: test case CRASHED: SIGSEGV - Segmentation violation signal error in "method(c);" (line: 5541)

FranckRJ commented 1 year ago

Don't create the mock on the heap, create it on the stack. And you need to specialize it otherwise it doesn't work.

zhlongfj commented 1 year ago

That means I can't use shared_ptr to wrap the point from mock().get()?

FranckRJ commented 1 year ago

You can, delete operator is overrided so it does nothing.

malcolmdavey commented 1 year ago

Yes override the delete operator

My code:
Mock mock1;
When(Method(mock1, resId)).AlwaysReturn("1");
auto meta = shared_ptr(mock1->get(), [](auto){});
malcolmdavey commented 1 year ago

Might be useful having this in the docs, though.

FranckRJ commented 1 year ago

What i mean is that you don't need to do anything. It works without any workaround.

FranckRJ commented 1 year ago
Mock mock1;
When(Method(mock1, resId)).AlwaysReturn("1");
auto meta = shared_ptr(mock1.get());

It's enough.

zhlongfj commented 1 year ago

Yes override the delete operator

My code:
Mock mock1;
When(Method(mock1, resId)).AlwaysReturn("1");
auto meta = shared_ptr(mock1->get(), [](auto){});

It works, thanks

zhlongfj commented 1 year ago

You can, delete operator is overrided so it does nothing.

It works, thanks

FranckRJ commented 1 year ago

I've looked a bit more into the source code to understand how it works, the summary (for GCC) is:

For visual studio it's a bit the same but instead of two destructors in the vtable there is only one that point to a wrapper that call "~Class()", etc (and free).

In the end, what you need to remember is that you have nothing special to do, use the pointer without worrying about any potential double free. You don't need to set any custom deleter / destructor.

FranckRJ commented 1 year ago

And also I wasn't able to reproduce the crash with a mock allocated on the heap : https://godbolt.org/z/dcTosana8

I mean, it isn't necessary so you shouldn't do it anyway but I still wonder why it crashed for you.

zhlongfj commented 1 year ago

the follow code is crashed in my VS2019(C++17), but It's OK in: https://godbolt.org/z/dcTosana8

class Demo { public: shared_ptr _meta; };

void testcase() { Mock mock2; When(Method(mock2, resId)).AlwaysReturn("1"); Demo demo; demo._meta = shared_ptr(&mock2.get()); }

crash info: 0x0000000000000000 Exception raised at TimelineUnitTest.exe: 0xC0000005: Access conflict occurred at execution location 0x0000000000000000.

malcolmdavey commented 1 year ago

I'll double check tomorrow on my machine - also with VS 2019.

malcolmdavey commented 1 year ago

I've also found I need to do this on VS 2019/v142. There may be a bug with it on VS

malcolmdavey commented 1 year ago

This may also be fixed by this I think. https://github.com/eranpeer/FakeIt/pull/289

FranckRJ commented 1 year ago

Fixed by #289 in FakeIt 2.3.1.