内存泄漏,指向文字的指针

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存泄漏,指向文字的指针相关的知识,希望对你有一定的参考价值。

我已经学会了不要让指针指向文字,因为它会导致内存泄漏。但是当我指定一个文字的指针时,它仍然指向与以前相同的地址:

    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;

我每次仍然得到相同的内存地址:

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

当我让指针指向文字时,地址不应该改变吗?我认为我用new分配的内存应该在RAM中,而文字应该在ROM中,它应该有不同的地址。我错了吗?

谢谢你,菲利普

答案

你的cout指令正在打印名为testpointer的变量的地址。这是当前函数的堆栈帧中的某个位置。它与testpointer的值无关,也与testpointer指出的值无关。

此外,无论是谁告诉你你不应该让指针指向一个文字是疯了,或者你不明白他们对你说了什么。让指针指向文字是绝对没有问题的。

另一答案

&testpointer是指向变量testpointer的指针。这是变量本身的存储位置。

如果你想打印testpointer指向的位置,你打印它的值(作为void*,否则operator<<会将其打印为字符串):

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

另请注意,在现代计算机上,实际上没有ROM。可执行映像从磁盘加载到虚拟内存(“RAM”)中,包括常量字符串文字(实际上是常量字符数组)等数据。

此外,您可以指向常量字符串文字,但它们应该是指向const char的指针,因为常量字符串文字是常量。问题在于重新分配变量。你会遇到同样的问题,例如

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

如果在第二个delete[]之前没有new[],那么你有内存泄漏。

最后关于你使用std::strncpy的警告:它不会在最后添加终止''。那是因为你提供的大小(第三个参数)小于或等于源字符串的长度,在这种情况下函数不会添加终结符。因此,不要尝试打印“字符串”的内容或将其用作“字符串”。

另一答案

你的问题有两个误解。

一,你打印的是testpointer的地址而不是它的值,所以它显然没有改变。如果用&testpointer替换static_cast<void*>(testpointer),你会看到差异。请注意,强制转换是必要的,因为<<重载char*以打印字符而不是指针本身。

二,

不要让指针指向文字,因为它会导致内存泄漏

根本不是真的。当且仅当您有一些动态分配的内存并且丢失对该内存的任何引用时,才会发生泄漏;换句话说,如果你不再有指向那个记忆的指针。在这种情况下,您不再有办法解除分配内存,因此泄漏它。

这通过执行以下操作序列在您的程序中发生:

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

它们中的任何一个都是好的(1),但是它们一起导致泄漏:

  1. 首先,你分配内存
  2. 然后,你忘记了它的地址(通过将指针指向别处)。

请注意,涉及的文字是无关紧要的。这将是完全相同的泄漏:

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

就像这样:

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

(1)除非你将char *指向字符串文字,这是自C ++ 11以来不允许的,因为字符串文字是const。你需要一个const char *

另一答案

我已经学会了不要让指针指向文字,因为它会导致内存泄漏。

指向字符串文字不会导致内存泄漏。可以指向字符串文字。

顺便说一句,你的程序确实泄漏了内存。


但是当我指定一个文字的指针

初始化后,程序不会指定指针。

它仍然指向与以前相同的地址:

您不会流式传输指针指向的地址。您在指针变量上使用addressof运算符,因此您可以流式传输指针所在的地址。即使您指定了指针,这也不会改变。


当我让指针指向文字时,地址不应该改变吗?

指针变量的地址不会改变。但它指向的地址(即指针的值)会改变。但是你既没有指向字符串文字,也没有观察到指向的地址。

以上是关于内存泄漏,指向文字的指针的主要内容,如果未能解决你的问题,请参考以下文章

转《js闭包与内存泄漏》

访问指向结构的指针会导致内存读取冲突

在函数中留下指针会导致内存泄漏吗?

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

C++:OpenMP 并行循环内存泄漏

C/C++——指针