看不见的内存泄漏? - malloc 和 strcpy
Invisible memory leak? - malloc and strcpy
我编译了我的代码,前两次它崩溃了。我没有改变任何东西并再次编译,第三次和第四次编译过程运行良好,没有任何崩溃。
前两次崩溃并没有立即发生,它已经打印了我的printf语句,立即被强行关闭。
这是我的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char testString[] = "Yiu Rules";
char* destString = (char*)malloc(sizeof(strlen(testString))*2);
strcpy(destString, testString);
printf("%s", destString);
free(destString);
return 0;
}
有什么想法吗?
sizeof(strlen(testString))
不是你想的那样。您计算 strlen
返回值的大小(以字节为单位),即 size_t
.
只需使用 strlen(testString)
.
这就是 strcpy
不是安全函数的原因,您应该使用 strncpy
。
您分配了 sizeof(strlen(testString)) * 2
字节的内存。这似乎没有道理。 sizeof(strlen(testString)) * 2
是 sizeof(size_t) * 2
,这通常是你的字符串不够用。
sizeof(size_t) * 2
在 64 位或 32 位平台上通常分别是 16 或 8 字节的内存。在 64 位平台上,您的代码将 "survive",因为您的字符串适合 16 个字节。但在 32 位平台上它不适合,它会溢出分配的内存并损坏堆。
这个
char* destString = malloc(strlen(testString) * 2);
会有些道理(如果你想尝试过度分配内存),但我不清楚 sizeof
的来源和原因。
sizeof(strlen(testString)) 确实不正确,但它仍然显示了一个很好的做法,即使用应用于 char 类型的 sizeof 运算符。在您的情况下,您在 size_t 上使用 sizeof 这不是您想要的,strlen 已经为您提供了要传递给 malloc 的字节数,但是如果您也想使用 sizeof,这是一种正确的方法这样做:
(char *)malloc(sizeof(char) * strlen(testString) * 2 + 1).
注意 malloc 末尾的 + 1:strlen 不计算它计算长度的字符串的终止 NULL 字节。然后你的 strcpy 可能会工作,但你最终也可能会遇到总线错误或某种错误,因为你试图将 \0 (在 strcpy 中)附加到内存的未保留部分。
此外,你的 malloc 可能 return 你已经使用了内存区域(但它很少发生在像你提供的那样的短程序中)所以你可以在分配后立即使用 bzero 以确保你正在清理内存。
我编译了我的代码,前两次它崩溃了。我没有改变任何东西并再次编译,第三次和第四次编译过程运行良好,没有任何崩溃。
前两次崩溃并没有立即发生,它已经打印了我的printf语句,立即被强行关闭。
这是我的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char testString[] = "Yiu Rules";
char* destString = (char*)malloc(sizeof(strlen(testString))*2);
strcpy(destString, testString);
printf("%s", destString);
free(destString);
return 0;
}
有什么想法吗?
sizeof(strlen(testString))
不是你想的那样。您计算 strlen
返回值的大小(以字节为单位),即 size_t
.
只需使用 strlen(testString)
.
这就是 strcpy
不是安全函数的原因,您应该使用 strncpy
。
您分配了 sizeof(strlen(testString)) * 2
字节的内存。这似乎没有道理。 sizeof(strlen(testString)) * 2
是 sizeof(size_t) * 2
,这通常是你的字符串不够用。
sizeof(size_t) * 2
在 64 位或 32 位平台上通常分别是 16 或 8 字节的内存。在 64 位平台上,您的代码将 "survive",因为您的字符串适合 16 个字节。但在 32 位平台上它不适合,它会溢出分配的内存并损坏堆。
这个
char* destString = malloc(strlen(testString) * 2);
会有些道理(如果你想尝试过度分配内存),但我不清楚 sizeof
的来源和原因。
sizeof(strlen(testString)) 确实不正确,但它仍然显示了一个很好的做法,即使用应用于 char 类型的 sizeof 运算符。在您的情况下,您在 size_t 上使用 sizeof 这不是您想要的,strlen 已经为您提供了要传递给 malloc 的字节数,但是如果您也想使用 sizeof,这是一种正确的方法这样做:
(char *)malloc(sizeof(char) * strlen(testString) * 2 + 1).
注意 malloc 末尾的 + 1:strlen 不计算它计算长度的字符串的终止 NULL 字节。然后你的 strcpy 可能会工作,但你最终也可能会遇到总线错误或某种错误,因为你试图将 \0 (在 strcpy 中)附加到内存的未保留部分。
此外,你的 malloc 可能 return 你已经使用了内存区域(但它很少发生在像你提供的那样的短程序中)所以你可以在分配后立即使用 bzero 以确保你正在清理内存。