1
shared_ptr<void> t(new char[num])

means memory leak?

If so, what is the correct practice in this case.

should I use shared_array<> instead?

I'm editing the bytes pointed by 't' manually for later transfer in a TCP Stream.

Alon Amir
  • 4,913
  • 9
  • 47
  • 86
  • 3
    A correct practice is not to use `void` as shared_ptr's template type. – BЈовић Oct 24 '11 at 19:29
  • Why would that cause a memory leak in any case? `shared_ptr` works on array types doesn't it? `unique_ptr` does. – Mooing Duck Oct 24 '11 at 19:30
  • @VJo: Thanks, but the reason I'm using a void* is because I'm allocating 'num' bytes for storage of different types of variables, like the first 4 bytes represent a double, next 2 bytes are short. – Alon Amir Oct 24 '11 at 19:32
  • 3
    Calling delete on a pointer-to-void results in undefined behavior. Don't do that. http://stackoverflow.com/questions/1293326/deleting-pointer-sometimes-results-in-heap-corruption/1708737#1708737 – Nemo Oct 24 '11 at 19:32
  • 1
    Note that this will call `operator delete`, not `operator delete[]`, which is twice undefined (pointer-to-void, and not an array). This will _possibly_ work just fine, but it may _quite possibly_ crash, or leak, or do any other possible thing. – Damon Oct 24 '11 at 19:33
  • @VJo, Damon's point is that on another compiler it might appear to work. Never try to pin down the exact consequence of UB because it's pointless. – Mark Ransom Oct 24 '11 at 19:40
  • what if I type char instead of void & replace shared_ptr with shared_array so delete[] is called? – Alon Amir Oct 24 '11 at 19:49
  • There's an awful lot of misinformation about `shared_ptr` in these answers... which I'm guessing is why http://stackoverflow.com/q/7881003/293791 popped up. – Dennis Zickefoose Oct 24 '11 at 19:57
  • @DennisZickefoose - Thanks! I was obviously parroting what I read, without thinking for myself. Hopefully my answer is beter now. – Robᵩ Oct 24 '11 at 20:35

5 Answers5

3

As I see the void You mention in the Q is a typo, Since Calling delete on a void * is guaranteed Undefined Behavior by the Standard.

For another data type,

You will have to provide your custom deletor to the shared_ptr so you can call delete [].

Eg:

For example:

template<typename T>
struct Customdeleter
{
   void operator()(T* p)
   {
      delete [] p;
   }
};

And invoke as:

shared_ptr<char> sp(new char[num], Customdeleter<char>());

EDIT:
Since you clarified are using Boost in comments and not TR1(AFAIK TR1 doesn't have shared_array)

You can use shared_array:

shared_array<char> sp(new char[num])
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Still undefined behavior to call delete[] on void* – Pubby Oct 24 '11 at 19:36
  • A custom deleter is an option, but i prefer to avoid using these, is there another way? what if i type char instead of void & replace shared_ptr with shared_array so delete[] is called? – Alon Amir Oct 24 '11 at 19:40
  • @AlonAmir: AFAIK, TR1 does not have a shared_array.So Custom deleter is the way to go about it. – Alok Save Oct 24 '11 at 19:42
  • I'm using boost because I'm cross compiling over iOS and the NDK on adnroid – Alon Amir Oct 24 '11 at 19:45
  • @AlonAmir: Then yes you should use shared_array. Sorry I was confused by the TR1 tag in the Question. – Alok Save Oct 24 '11 at 19:49
3

means memory leak?

No, it means undefined behavior. (Which could have any symptom, including memory leak.) The call to delete must match the call to new. Yours doesn't. You allocate with new[] but destroy with delete.

If so, what is the correct practice in this case. Should I use shared_array<> instead?

There are two easy choices. You can use shared_array:

shared_array<char> t(new char[num])
t[7] = 42;

Or, you could use a shared_ptr to a std::vector:

shared_ptr<std::vector<char> > t(new std::vector<char>(num))
(*t)[7] = 42;


EDIT: Thanks to @Dennis Zickefoose for gently pointing out an error in my thinking. Parts of my answer are rewritten.
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • Makes sense. I'm not equipped with a Profile/Analyze utility ATM, so I have no way to verify it, but I'm counting on it for now. – Alon Amir Oct 24 '11 at 19:55
1

I think I see where you're coming from - you want void * pointers so you can later cast it to the final type you're serializing. But as others have pointed out, you can't delete a void* pointer, and neither can the code for shared_ptr.

Since you're allocating an array of char, that should be the type of smart pointer you use:

shared_array<char> t(new char[num]);

Casting the raw char pointer to another type shouldn't be any more of a problem than casting a void* pointer.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

You're calling delete on void* which is undefined behavior.

the reason I'm using a void* is because I'm allocating 'num' bytes for storage of different types of variables, like the first 4 bytes represent a double, next 2 bytes are short..

Use a struct or union then.

Pubby
  • 51,882
  • 13
  • 139
  • 180
  • This should probably be merged to a comment. – Pubby Oct 24 '11 at 19:34
  • Using shared_ptr is not undefined behavior - http://stackoverflow.com/questions/7881003/why-is-shared-ptrvoid-not-specialized - it's use is also encouraged - http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/sp_techniques.html#pvoid – Natalie Adams Sep 15 '13 at 19:18
0

I don't know if C++11 has a shared_array, but Boost does — you should use that instead.

Paul Manta
  • 30,618
  • 31
  • 128
  • 208