简体   繁体   中英

memory leak, pointer to literal

I've learned not to let pointer point to literals because it causes memory leaks. But when I assign a pointer to a literal, it still points to the same address than before:

    unsigned maxlen = 20;
    char* testpointer = new char[sizeof(char) * maxlen]; //Pointer points to RAM
    cout << "&testpointer = " << &testpointer << endl;

    strncpy(testpointer, "Happy Eastern", 13);
    cout << "&testpointer = " << &testpointer << endl;

    testpointer = "Merry Christmas"; // I know I shouldn't do this
    cout << "&testpointer = " << &testpointer << endl;

I still get the same memory address each time:

&testpointer = 0x28fc60
&testpointer = 0x28fc60
&testpointer = 0x28fc60

Shouldn't the address change when I let the pointer point to a literal? I thought the memory which I allocated with new should be in RAM while the literal should be in ROM, which should have a different address. Am I wrong?

Thank you, Philipp

Your cout instructions are printing the address of the variable called testpointer . That's some location in the stack frame of the current function. It has nothing to do with the value of testpointer , nor with the value pointed by testpointer .

Also, either whoever told you that you should not let a pointer point to a literal was mad, or you did not understand what they said to you. There is absolutely no problem with letting a pointer point to a literal.

&testpointer is a pointer to the variable testpointer . It's where the variable itself is stored.

If you want to print where testpointer is pointing, you print its value (as a void* since otherwise operator<< will print it as a string):

std::cout << "testpointer = " << static_cast<void*>(testpointer) << '\n';

Also note that on modern computers there's really no ROM. The executable image is loaded from the disk into the virtual memory ("RAM") and that includes data such as constant string literals (which are really arrays of constant characters).

Also, you can have pointers to constant string literals, but they should really be pointers to const char since constant string literals are constant. The problem is with the reassignment of the variable. You would get the same problem with eg

unsigned maxlen = 20;
char* testpointer = new char[sizeof(char) * maxlen];
// ... stuff happens...
testpointer = new char[some_other_size];

If there's no delete[] before the second new[] , then you have a memory leak.

Finally a warning about your use of std::strncpy : It will not add the terminating '\\0' at the end. That's because your supplied size (the third argument) is smaller or equal to the length of the source string, in which case the function will not add the terminator. So don't attempt to print the contents of the "string" or use it as a "string".

There's two misconceptions in your question.

One , you're printing the address of testpointer instead of its value , so it's obviously not changing. If you replace &testpointer with static_cast<void*>(testpointer) , you will see the difference. Note that the cast is necessary, because << is overloaded for char* to print the characters instead of the pointer itself.

Two ,

not to let pointer point to literals because it causes memory leaks

is simply not true. A leak happens if and only if you have some dynamically allocated memory and lose any reference to that memory; in other words, if you no longer have a pointer to that memory. In such case, you no longer have a way to deallocate that memory, and hence you leak it.

This happens in your program by doing this sequence of operations:

char* testpointer = new char[sizeof(char) * maxlen];
testpointer = "Merry Christmas";

Either one of them is fine on its own (1) , but together, they cause a leak:

  1. First, you allocate memory
  2. Then, you forget its address (by pointing the pointer elsewhere).

Note that a literal being involved is irrelevant. This would be exactly the same leak:

char* testpointer = new char[sizeof(char) * maxlen];
testpointer = nullptr;

As would this:

char* testpointer = new char[sizeof(char) * maxlen];
testpointer = new char[sizeof(char) * maxlen];

(1) Except you're pointing a char * at a string literal, which is not allowed since C++11, because string literals are const . You'd need a const char * for that.

I've learned not to let pointer point to literals because it causes memory leaks.

Pointing to string literals does not cause memory leaks. It's fine to point to a string literal.

Incidentally, your program does leak memory.


But when I assign a pointer to a literal

Your program does not assign the pointer after initialization.

it still points to the same address than before:

You don't stream the address that the pointer points at. You use addressof operator on the pointer variable, so you stream the address where the pointer is stored. This wouldn't change even if you did assign the pointer.


Shouldn't the address change when I let the pointer point to a literal?

The address of the pointer variable wouldn't change. But the address it points to (ie the value of the pointer) would change. But you neither point to a string literal, nor do you observe the address that is pointed at.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM