由 strcpy 设置的解除分配字符 * 时内存泄漏?

Memory leak on deallocating char * set by strcpy?

本文关键字:内存 泄漏 字符 strcpy 设置 解除分配      更新时间:2023-10-16

我有一个内存泄漏检测器工具,它告诉我下面的代码泄漏了 100 字节

#include <string>
#include <iostream>
void setStr(char ** strToSet)
{
strcpy(*strToSet,  "something!");
}
void str(std::string& s)
{
char* a = new char[100]();
setStr(&a);
s = a;
delete[] a;
}
int main()
{
std::string s1;
str(s1);
std::cout << s1 << "n";
return 0;
}

根据第 3 点,它泄漏了我分配的数量 (100) 减去"something!"(10) 的长度,我应该泄漏 90 个字节。

我在这里遗漏了什么,还是可以安全地假设该工具报告错误?

编辑:setStr()在库中,我看不到代码,所以我猜它正在这样做。可能是它在堆上分配"something!",这种情况呢?我们会有 90 字节泄漏还是 100 字节泄漏?

此代码不会泄漏,并且与第 3 点不同,因为您永远不会覆盖存储指向已分配内存的指针的变量。此代码的潜在问题是它容易受到缓冲区溢出的影响,就好像setStr打印超过 99 个符号一样,并且它不是异常安全的,就像s = a;抛出然后delete[] a;不会被调用并且内存会泄漏一样。

已更新:如果setStr分配新字符串并覆盖初始指针值,则指向已分配的 100 字节缓冲区的指针将丢失,并且这 100 个字节会泄漏。在将a传递给setStr之前,应使用nullptr对其进行初始化,并在setStr返回后检查它是否不为 null,以便赋值s = a;不会导致 null 指针取消引用。

总结所有评论,问题是什么就很清楚了。您正在使用的库正在请求char **。这是分配内存并返回指向该内存的指针或返回指向它们拥有的内存的指针的 C 函数的常见接口模式。

您泄漏的内存在行char* a = new char[100]();中分配。因为setStr正在更改a的值,所以您不能再释放该内存。

不幸的是,如果没有文档,我们无法推断您应该使用指针做什么。

  • 如果是来自呼叫new[]则需要呼叫delete[]

  • 如果是来自呼叫malloc则需要呼叫std::free

  • 如果它是指向库拥有的内存的指针,则不应执行任何操作。

您需要找到这方面的文档。但是,如果不可用,则可以在删除new语句后尝试使用内存泄漏检测工具,并查看它是否检测到泄漏。我不确定从库函数分配的内存是否可靠,但值得一试。

最后,关于编辑中的问题,如果你泄漏了内存,你就泄漏了全部内存,除非你做了一些未定义的行为,无论如何讨论都是没有意义的。如果您new100char秒,然后在它们上写入一些数据,这不会改变泄漏的内存量。它仍然会100 * sizeof(char)