为什么这会导致堆损坏?

Why this causing Heap corruption?

为什么这段代码在尝试删除 [] 全名变量时导致堆损坏?

#include <iostream>
#include <cstring>
#include "stdafx.h"

using namespace std;


int main() {
    const int size = 255;
    char* firstname = new char[size];
    char* lastname = new char[size];
    cin.getline(firstname, size, '\n');
    cin.getline(lastname, size, '\n');

    int fullnamesize = strlen(firstname) + strlen(lastname) + 2;
    cout << "fullname size: " << fullnamesize;
    char* fullname = new char[fullnamesize];
    strcpy_s(fullname, size, firstname);
    strcat_s(fullname, size, " ");
    strcat_s(fullname, size, lastname);

    cout << "full name: " << fullname << "\n" ;

    delete[] fullname;
    delete[] firstname;
    delete[] lastname;  

    cout << "hello";
    return 0;
}

我找不到这个分配有什么问题...

这是怎么回事? 它实际上在 strcpy_s 处出错了。因为 strcpy_s 首先覆盖目标缓冲区(到函数调用中指定的大小)。参见 https://msdn.microsoft.com/en-us/library/td1esda9.aspx -

The debug versions of these functions first fill the buffer with 0xFE. To disable this behavior, use _CrtSetDebugFillThreshold.

(我承认这很微妙!)

并且您的目标缓冲区大小错误,因此您的内存被覆盖,因为您只为全名分配了足够的内存,但您传递的大小参数更大。

为什么它在 delete[] 而不是 strncpy 时崩溃?

delete[] 处的释放没有任何问题。在您到达那里之前,问题就已经发生了。

程序不知道您传入了错误的大小。但是 strcpy 函数覆盖了堆中的内存管理结构。在 delete[] 调用之前,这不会导致任何问题。 Delete 尝试使用该信息并发现它已损坏。然后你会崩溃。

在大型程序中,此类问题完全是一场噩梦。

正确的做法是什么?

使用安全字符串函数是个好主意,但您需要仔细阅读它们的手册以确保获得正确的结果。并且要更加小心你传递给他们的尺寸。

*PS。理解旧的 strcpy 和 char * 方法很重要,但在长 运行 中,为了获得健壮的代码,请研究 std::string*