看似不错的删除 [] 程序崩溃

Posted

技术标签:

【中文标题】看似不错的删除 [] 程序崩溃【英文标题】:Program crash on seemingly fine delete[] 【发布时间】:2019-05-21 16:07:21 【问题描述】:

我正在使用 Visual C++ 2017 构建 OpenGL/GLFW 应用程序。但是,我在delete[] 语句上遇到了崩溃,并显示消息“HEAP CORRUPTION DETECTED : [...] CRT 检测到应用程序在堆缓冲区结束后写入内存。”在我写的以下函数中:

#include <direct.h>

void setwd(char **argv)

    char *buf = new char[strlen(argv[0])];
    strcpy(buf, argv[0]);
    // Handle both possible separators
    char *p = strrchr(buf, '/');
    if(!p)
        p = strrchr(buf, '\\');
    if(p)
    
        *(p + 1) = '\0';
        _chdir(buf);
    
    delete[] buf;

如果我删除对setwd 的呼叫,一切正常。我在调试时确保strlen(argv[0]) 永远不会为0。

值得注意的是,如果使用 MSYS2/gcc 编译,这将完全正常。

【问题讨论】:

被一个错误关闭。缓冲区太小,无法容纳字符串。 减少您的缺陷数量并使用std::string 作为文本。 std::string 自动为您管理内存,并具有搜索和替换方法。 不要自己管理内存。把它留给底层结构的实现者。使用字符串/向量为您执行此操作。 【参考方案1】:

缓冲区中需要一个额外的字符,用于空终止符:new char[strlen(argv[0])+1]

【讨论】:

好吧,这行得通。愚蠢的错误,但为什么它在 MSYS 上运行良好,最重要的是,为什么要等到 delete[] 运算符失败?这是超级误导。 @Matrefeytontias 这是未定义的行为,所以究竟会发生什么取决于您的实现的具体细节。在这种情况下,您的标准库的堆分配器可能会在从new 返回的每个内存块之后存储一些有用的东西(例如,分配的大小,或指向某些已分配对象列表中下一个内存块的指针),并且你覆盖了它。然后,当实现尝试读取此信息时,它会感到困惑。使用另一个工具链,您的新/删除实现可能会以不同的方式工作并且很好。 对我来说已经足够了。谢谢你的解释! @Matrefeytontias 我赞同其他人的建议,即使用std::string 而不是原始字符数组。它们更容易正确使用而不会导致错误,主要是因为它们会自动管理自己的内存,而无需您担心。

以上是关于看似不错的删除 [] 程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

reloadRowsAtIndexPaths:withRowAnimation: 使我的应用程序崩溃

NSFetchedResultsController:删除 1 行使应用程序崩溃

删除函数正在使程序崩溃 c++

从 ScrollableView 中删除页面时,Titanium 应用程序崩溃

如果用户从设置中删除应用程序权限,应用程序崩溃

删除部分的最后一行后,应用程序崩溃