内存导致程序崩溃并带有初始化的目的地



我正在开发一个更大的程序,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;
}

我不确定为什么会发生这种情况。有人可以解释一下为什么它会崩溃吗?

谢谢!

memcpy导致错误的原因是您尝试将s1的内容复制到字符串文本指向的内存中,这是未定义的行为,因为字符串文本不可写,即使它们是,也没有足够的空间。

您的第一个代码也是无效的,因为它使memcpy进入由未初始化的指针指向的内存 - 再次是一种未定义的行为。

您可以通过添加对 new 的调用来修复第一段代码,如下所示:

char* s2 = new char[strlen(s1)+1];

第二段代码可以像这样修复:

char s2[5] = "";

这两个程序都有未定义的行为。因此,如果第一个没有崩溃(它取消引用未初始化的指针!),那只是你不走运。

目标(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

顺便说一句,要非常小心地避免缓冲区溢出。上面的代码有效,因为在这种情况下strlen(s1)小于 31。