1

I'm using a unique_ptr to pass a const wchar_t pointer to a function. In the following I would like to give a short example:

bool MyClass::foo(unique_ptr<const wchar_t> display_name) {
  bool result = false;
  ....
  // Do something
  result = DoWork(display_name.get());
  ....
  // I have to call release to prevent getting an error
  display_name.release();
  return result;
}

Until now I thought I don't have to call the release() method of a unique_ptr before leaving the scope (return from function) because the content of the unique_ptr will automatically be deleted if the unique_ptr runs out of scope. But if don't call the release() method I get the following error (VS 2010):

enter image description here

I think this error message occurs because the memory isn't correctly freed? What's the recommended approach dealing with unique_ptr, which is passed as an argument?

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
ferraith
  • 899
  • 1
  • 8
  • 19
  • 1
    Tell (or better: show) us how `display_name` is allocated. – 01d55 Dec 28 '11 at 21:15
  • No no no ... have you heard of `std::wstring`? FYI the error is because of the `const` the `release()` appears to fix it because then the smart point doesn't call `delete` as you've taken back ownership of the pointer and either leaked it or cleaned it up yourself. Regardless this is an improper use of a smart pointer. – AJG85 Dec 28 '11 at 21:19
  • display_name is defined like this: unique_ptr display_name(L"CharlieCore"); – ferraith Dec 28 '11 at 21:23
  • I know wstring, but the const wchar_t * is passed to a winapi function so I have to use this datatype instead of wstring. The DoWork() function is a WinAPI function (CreateService) – ferraith Dec 28 '11 at 21:24
  • 1
    @Flasher: That definition of `unique_ptr` is dangerous because `L"CharlieCore"` is not dynamically allocated with non-array `new`. It isn't dynamically created at all so `unique_ptr` is unnecessary. The only way to construct a valid `unique_ptr` for such as string would be with a custom "do nothing" deleter. – CB Bailey Dec 28 '11 at 21:31
  • @Flasher: See my answer for how to use `std::wstring` with windows API and a bit of an explanation of when and why you would use `std::unique_ptr` – AJG85 Dec 28 '11 at 21:51

2 Answers2

3

Based on your description and comment I believe this is more what you are looking for:

bool MyClass::foo(const std::wstring& display_name)
{
  bool result = false;

  // Do something
  result = DoWork(display_name.c_str());

  return result;
}

This string object is a STL container of wchar_t that has various helpful methods. One of which is c_str() which returns a c-style const wchar_t* version of the string contents for backwards compatibility with older code. Your DoWork function may be such a function that requires a c-style string so the above will work for you.


Now onto smart pointers 101:

In C++11 std::unique_ptr can be used to automatically destruct objects allocated on the heap freeing from the worries of exception unsafe code and manual memory management which can lead to memory leaks and other bad things. Say you had the following code:

void LeakyFunction()
{
    double* ptr = new double;
}

Obviously that's a memory leak as once the scope of LeakyFunction ends we've lost the pointer on the stack and no longer can delete what it was pointing to on the heap. So we write this:

void LessLikelyLeakyFunction()
{
    double* ptr = new double;
    // do stuff
    delete ptr; // clean up heap
}

That's well and dandy unless you have an early return or throw an exception during the do stuff portion of code which puts you back to the same problem as before. So people started writing custom smart pointer classes which owned raw memory allocation by allocating on construction and deallocating on destruction. This concept has now become standard via things like std::unique_ptr so we can do the following:

void SmartFunction()
{
    std::unique_ptr<double> ptr(new double);
    // do stuff
} // unique_ptr is smart and calls delete for you

In this way no matter when the scope of the function ends you don't have to worry things will be cleaned up properly. In short if you aren't using new you don't need a smart pointer and if you are then you probably should use a smart pointer to make your code more robust.

AJG85
  • 15,849
  • 13
  • 42
  • 50
  • Thank you for your detailed answer. I will modify my code to use wstrings and clean out the unnecessary smart pointers. – ferraith Dec 28 '11 at 21:56
  • @Flasher: You also might want to check out this extensive list of books worth reading: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – AJG85 Dec 28 '11 at 22:05
2

Via unique_ptr, you are attempting to call delete on a pointer to a string literal constant.

You must only allow delete to be called on pointers that point to objects created using new.

JoeG
  • 12,994
  • 1
  • 38
  • 63
  • Isn't it necessary to clean the memory of variables which I have created in the following way: const wchar_t *str = L"HelloWorld"; ? – ferraith Dec 28 '11 at 21:36
  • @Flasher: No. String literals don't have to be explicitly deallocated. – CB Bailey Dec 28 '11 at 21:41
  • Which raises the question: How do you initialize a unique_ptr without a deleter - pass in a no-op lambda in the constructor? Maybe `unique_ptr display_name(L"CharlieCore", []{})` (Of course, maybe the questioner shouldn't even use a unique_ptr in this case) – Aaron McDaid Dec 28 '11 at 21:57