为什么会导致堆腐败?

时间:2015-05-14 18:50:36

标签: c++ visual-c++

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

#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;
}

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

1 个答案:

答案 0 :(得分:3)

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

  

这些函数的调试版本首先使用0xFE填充缓冲区。   要禁用此行为,请使用_CrtSetDebugFillThreshold。

(我承认这非常微妙!)

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

为什么它会在删除[]而不是strncpy时崩溃?

删除[]时的重新分配没有任何问题。问题发生在你到达那里之前。

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

在大型项目中,这类问题是一场彻头彻尾的噩梦。

什么是正确的做法?

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

* PS。旧的strcpy和char *方法很重要,但从长远来看,对于健壮的代码,请研究std :: string *