1

I'm working on a image treating application.

In summary, I have a byte buffer which stores the image data, so I can use this array to handle the image easily in wx widgets and OpenCV. I planned to store this byte buffer in a shared_ptr as it will be used in other instances of the same class along the execution.

With raw pointer it works properly, but whenever I tried to use shared_ptr I'm having an segmentation fault whenever passing this pointer to a function.

How can I pass it to this function without segmentation fault? it doesn't make sense to me this crashing

The bug is here

_dataSize = (size_t)len;
_originalData = std::make_shared<void*>(malloc(_dataSize));
if ( file.Read(_originalData.get(), _dataSize) != len )

on the last line of above code, I'm trying to pass the _original data pointer to Read function

Here's the full code, on the piece above, I just put the line that the bug is happening. On the full the code the bug is on src/Img.cpp file on line 18

Thank you

  • 3
    You don't make an allocation in the parameter passed to `make_shared`. See https://stackoverflow.com/questions/20895648/difference-in-make-shared-and-normal-shared-ptr-in-c – Den-Jason Sep 08 '21 at 09:33
  • And if you pass pointer generated by `malloc`, you have to pass a deleter which call `free`. – Jarod42 Sep 08 '21 at 09:37
  • Do you really want to have shared ownership of the `void*`, or do you want shared ownership of the object that the `void*` points to? – Caleth Sep 08 '21 at 09:38
  • `make_shared(arguments)` creates a new shared object of type `T` from `arguments`. `shared_ptr(p)` takes ownership of the object pointed to by `p`. – molbdnilo Sep 08 '21 at 09:38
  • In this case I want a shared ownership as during the runtime, it will be make copies of this buffer to other Img objects – João Lucas Gouveia Sep 08 '21 at 09:40
  • Shared ownership of what? As it stands you are sharing ownership of a *pointer* – Caleth Sep 08 '21 at 09:40
  • Shared ownership of buffer(_originalData). Maybe the pointer is not the best approach, but even storing a shared_ptr of void I'm having problems – João Lucas Gouveia Sep 08 '21 at 09:41

2 Answers2

4

_originalData.get() is a void**, not a void*.

To share ownership of that allocation, you need std::shared_ptr<void>, not std::shared_ptr<void*>. You also need to set the deallocation function, as it is undefined behaviour to delete a pointer that was malloced.

_originalData = std::shared_ptr<void>{ malloc(len), free }; // _originalData is a `std::shared_ptr<void>
if ( file.Read(_originalData.get(), len) != len )

Alternatively, since C++20, you could use a std::shared_ptr<char[]>, and not use malloc at all.

_originalData = std::make_shared_for_overwrite<char[]>{ len }; // _originalData is a `std::shared_ptr<char[]>
if ( file.Read(*_originalData, len) != len ) // implicit conversion of char* to void*
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Nice. I'll try your answer and give here a feedback. Thank you very much – João Lucas Gouveia Sep 08 '21 at 09:44
  • On this project, I cannot use C++20 for reasons that are not in my power to decide. But your solution on defining a delete function works, I did tried something similar previously, but on the declaration of shared_ptr, which seems to be not allowed. Btw, I implement your suggestion and it worked well, and also I save the C++20 code to use it preferably, when possible. Thank you very much again – João Lucas Gouveia Sep 08 '21 at 10:01
  • `std::make_shared_for_overwrite` - wasn't aware of that, thanks :) – Den-Jason Sep 08 '21 at 10:30
1

Take a look on what make_shared does.

It will try to Contruct an objet of type T sending the arguments you give to the constructor.

In your code, it will try to create a new void* object (passing mallocs retunr pointer as argument), which I believe you don't want to do.

Instead if you use the shared_pointer's object constructor descibed here on 3-7 it

Constructs a shared_ptr with ptr as the pointer to the managed object.

Which I think you want to do

Ivan
  • 1,352
  • 2
  • 13
  • 31