memcpy 导致程序因初始化目标而崩溃
memcpy causing program to crash with initialized destination
我正在开发一个更大的程序,memcpy 导致它崩溃。我在一个小程序中复制了这种情况,它做了同样的事情。我注意到由于某种原因这个程序运行良好
// Runs fine
#include <iostream>
int main() {
char* s1 = "TEST"; // src
char* s2; // dest
memcpy(s2, s1, strlen(s1) + 1);
std::cout << s2 << std::endl; // Should print "TEST"
return 0;
}
但是这个程序崩溃了
// Crashes
#include <iostream>
int main() {
char* s1 = "TEST"; // src
char* s2 = ""; // dest - Note the small change
memcpy(s2, s1, strlen(s1) + 1);
std::cout << s2 << std::endl; // Should print "TEST"
return 0;
}
我不确定为什么会这样。有人可以解释为什么它会崩溃吗?
谢谢!
两个程序都有 undefined behavior。所以如果第一个没有崩溃(它解引用了一个未初始化的指针!),那只是你运气不好。
目的地(memcpy
的第一个参数)应该是一个已分配且可写的区域。本地数组(或指向堆栈上本地数据的指针,可能在某些调用者的框架中) - 或者指向全局或静态数据的指针 - :
char arr[32];
memcpy (arr, s1, strlen(s1)+1);
或堆分配区域:
char*ptr = malloc(32);
if (!ptr) { perror("malloc"); exit(EXIT_FAILURE); };
memcpy (ptr, s1, strlen(s1)+1);
请注意,通常像 "ABC"
这样的文字字符串 不可 可写。它们位于只读数据段。
以上是C代码。如果您想要 C++ 代码,请使用 new
(但在 C++ 中,您应该使用 std::string
)
顺便说一句,要非常小心避免buffer overflows。上面的代码有效,因为在那种情况下 strlen(s1)
小于 31.
memcpy
导致错误的原因是您试图将 s1
的内容复制到字符串文字指向的内存中,这是未定义的行为,因为字符串文字不可写,即使可以,也不够 space.
您的第一个代码也无效,因为它使 memcpy
进入未初始化指针指向的内存 - 又是未定义的行为。
您可以通过添加对 new
的调用来修复第一段代码,如下所示:
char* s2 = new char[strlen(s1)+1];
第二段代码可以这样修改:
char s2[5] = "";
我正在开发一个更大的程序,memcpy 导致它崩溃。我在一个小程序中复制了这种情况,它做了同样的事情。我注意到由于某种原因这个程序运行良好
// Runs fine
#include <iostream>
int main() {
char* s1 = "TEST"; // src
char* s2; // dest
memcpy(s2, s1, strlen(s1) + 1);
std::cout << s2 << std::endl; // Should print "TEST"
return 0;
}
但是这个程序崩溃了
// Crashes
#include <iostream>
int main() {
char* s1 = "TEST"; // src
char* s2 = ""; // dest - Note the small change
memcpy(s2, s1, strlen(s1) + 1);
std::cout << s2 << std::endl; // Should print "TEST"
return 0;
}
我不确定为什么会这样。有人可以解释为什么它会崩溃吗?
谢谢!
两个程序都有 undefined behavior。所以如果第一个没有崩溃(它解引用了一个未初始化的指针!),那只是你运气不好。
目的地(memcpy
的第一个参数)应该是一个已分配且可写的区域。本地数组(或指向堆栈上本地数据的指针,可能在某些调用者的框架中) - 或者指向全局或静态数据的指针 - :
char arr[32];
memcpy (arr, s1, strlen(s1)+1);
或堆分配区域:
char*ptr = malloc(32);
if (!ptr) { perror("malloc"); exit(EXIT_FAILURE); };
memcpy (ptr, s1, strlen(s1)+1);
请注意,通常像 "ABC"
这样的文字字符串 不可 可写。它们位于只读数据段。
以上是C代码。如果您想要 C++ 代码,请使用 new
(但在 C++ 中,您应该使用 std::string
)
顺便说一句,要非常小心避免buffer overflows。上面的代码有效,因为在那种情况下 strlen(s1)
小于 31.
memcpy
导致错误的原因是您试图将 s1
的内容复制到字符串文字指向的内存中,这是未定义的行为,因为字符串文字不可写,即使可以,也不够 space.
您的第一个代码也无效,因为它使 memcpy
进入未初始化指针指向的内存 - 又是未定义的行为。
您可以通过添加对 new
的调用来修复第一段代码,如下所示:
char* s2 = new char[strlen(s1)+1];
第二段代码可以这样修改:
char s2[5] = "";