4

Is this behaviour guaranteed all the time ? The code below creates a char* pointer using temporary unique_ptr. I thought the unique_ptr should get destructed at the end of the statement. To my surprise, the char* still points to valid memory.

void Fill(char* str, long len)
{
    for(int i = 0; i < len; ++i)
        str[i] = 'a';
}

char* x = std::unique_ptr<char[]>(new char[100]).get();

Fill(x, 100);

std::cout << x << std::endl;
Jagannath
  • 3,995
  • 26
  • 30
  • 2
    What makes you think it's valid? Doesn't look valid to me. You have undefined behavior here. Undefined means it's allowed to fail in any way, including seeming to work, or working temporarily and causing problems much later, or causing problems only when the moon is full. – Ben Voigt Sep 01 '11 at 04:48
  • By "valid" I meant, x was getting the data filled by Fill() method and it is printing the data. I understand, it is a wrong assumption. – Jagannath Sep 01 '11 at 04:51
  • 2
    @jagansai: That's not valid. Just undefined. – Martin York Sep 01 '11 at 04:55
  • This would have probably failed in a release compile. Debug compilation is very lenient about abusing memory. – Eli Iser Sep 01 '11 at 05:01

3 Answers3

11

That is invoking undefined behavior. Undefined behavior means anything can happen, including having it appear to work. The temporary unique_ptr is in fact being destructed, and as a result deallocates the 100-element char array. You're reading and writing into a memory location that is not allocated to you anymore.

It just so happens that the memory pointed by x hasn't been allocated or read/written for something else by the time you're working with it. But that memory has been already deallocated by the temporary unique_ptr, so you're not supposed to mess with it.

Just do not do this. If you want to keep the array but not the unique_ptr, use release() instead.

In silico
  • 51,091
  • 10
  • 150
  • 143
1

It's true that x points to the allocated memory, but that memory has been deallocated at the end of the statement, and what now x points to is illegal memory, and attempting to use it invokes undefined behaviour.

The program appears to work because the memory has not been allocated to another process. But there is no guarantee that the memory will not be allocated to another process.

Read this best explanation by @Eric Lippert here:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Virtual address space is private to each process, it can never be "allocated to another process". The risk is that it's reused within the process for some other object. – Ben Voigt Sep 01 '11 at 14:10
1

Since you haven't assigned to a variable of type unique_ptr, you have only created a temporary. The memory is freed as soon as x is initialized, before Fill is called at all.

Simply do this:

std::unique_ptr<char[]> x(new char[100]);

Fill(x.get(), 100);

As the others have said, it's just luck that your program didn't crash. Crashes are seldom guaranteed.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421