简体   繁体   English

程序仅在调试器外部的发布模式下崩溃

[英]Program crashes only in Release mode outside debugger

I have quite massive program (>10k lines of C++ code). 我有相当大的程序(> 10k行的C ++代码)。 It works perfectly in debug mode or in release mode when launched from within Visual Studio, but the release mode binary usually crashes when launched manually from the command line (not always!!!). 从Visual Studio中启动时,它在调试模式或发布模式下都能正常工作,但是从命令行手动启动时,释放模式二进制文件通常会崩溃(并不总是!!!)。

The line with delete causes the crash: 删除行会导致崩溃:

bool Save(const short* data, unsigned int width, unsigned int height, 
          const wstring* implicit_path, const wstring* name = NULL, 
          bool enable_overlay = false)
{
    char* buf = new char[17];
    delete [] buf;
}

EDIT: Upon request expanded the example. 编辑:根据请求扩展了示例。

The "len" has length 16 in my test case. 在我的测试用例中,“len”长度为16。 It doesn't matter, if I do something with the buf or not, it crashes on the delete. 没关系,如果我对buf做了一些事情,它会在删除时崩溃。

EDIT: The application works fine without the delete [] line, but I suppose it leaks memory then (since the block is never unallocated). 编辑:应用程序工作正常没有删除[]行,但我想它会泄漏内存(因为块永远不会被分配)。 The buf in never used after the delete line. 删除行后从未使用的buf。 It also seems it does not crash with any other type than char. 它似乎也不会与除char之外的任何其他类型崩溃。 Now I am really confused. 现在我真的很困惑。

The crash message is very unspecific (typical Windows "xyz.exe has stopped working"). 崩溃消息非常不明确(典型的Windows“xyz.exe已停止工作”)。 When I click the "Debug the program" option, it enters VS, where the error is specified to be "Access violation writing location xxxxxxxx". 当我单击“调试程序”选项时,它进入VS,其中错误被指定为“访问冲突写入位置xxxxxxxx”。 It is unable to locate the place of the error though "No symbols were loaded for any stack frame". 虽然“没有为任何堆栈帧加载符号”,但无法找到错误的位置。

I guess it is some pretty serious case of heap corruption, but how to debug this? 我想这是一个非常严重的堆损坏案例,但如何调试呢? What should I look for? 我应该寻找什么?

Thanks for help. 感谢帮助。

have you checked memory leaks elsewhere? 你有没有检查其他地方的内存泄漏?

usually weird delete behavior is caused by the heap getting corrupted at one point, then much much later on, it becomes apparent because of another heap usage. 通常奇怪的删除行为是由于堆在某一点上被破坏引起的,然后在很久之后,由于另一个堆的使用而变得明显。

The difference between debug and release can be caused by the way windows allocate the heap in each context. 调试和发布之间的区别可能是由Windows在每个上下文中分配堆的方式引起的。 For example in debug, the heap can be very sparse and the corruption doesn't affect anything right away. 例如,在调试中,堆可能非常稀疏,并且损坏不会立即影响任何内容。

The biggest difference between launched in debugger and launched on its own is that when an application is lunched from the debugger Windows provides a "debug heap", that is filled with the 0xBAADF00D pattern; 在调试器中启动并自行启动的最大区别在于,当从调试器中启动应用程序时,Windows提供了一个“调试堆”,它填充了0xBAADF00D模式; note that this is not the debug heap provided by the CRT, which instead is filled with the 0xCD pattern (IIRC). 请注意,这不是CRT提供的调试堆,而是填充了0xCD模式(IIRC)。

Here is one of the few mentions that Microsoft makes about this feature, and here you can find some links about it. 是微软为此功能提供的少数几个提及之一,在这里您可以找到一些关于它的链接。

Also mentioned in that link is "starting a program and attaching to it with a debugger does NOT cause it to use the "special debug heap" to be used." 该链接中还提到“启动程序并使用调试器附加到程序中不会导致它使用”特殊调试堆“。”

You probably have a memory overwrite somewhere and the delete[] is simply the first time it causes a problem. 您可能在某处有内存覆盖,而delete []只是第一次导致问题。 But the overwrite itself can be located in a totally different part of your program. 但覆盖本身可以位于程序的完全不同的部分。 The difficulty is finding the overwrite. 困难在于找到覆盖。

Add the following function 添加以下功能

#include <malloc.h>

#define CHKHEAP()  (check_heap(__FILE__, __LINE__))

void check_heap(char *file, int line)
{
    static char *lastOkFile = "here";
    static int lastOkLine = 0;
    static int heapOK = 1;

    if (!heapOK) return;

    if (_heapchk() == _HEAPOK)
    {
        lastOkFile = file;
        lastOkLine = line;
       return;
    }

    heapOK = 0;
    printf("Heap corruption detected at %s (%d)\n", file, line);
    printf("Last OK at %s (%d)\n", lastOkFile, lastOkLine);
}

Now call CHKHEAP() frequently throughout your program and run again. 现在,在整个程序中经常调用CHKHEAP()并再次运行。 It should show you the source file and line where the heap becomes corrupted and where it was OK for the last time. 它应该显示源文件和堆损坏的行以及最后一次它可以的位置。

There are many possible causes of crashes. 崩溃有很多可能的原因。 It's always difficult to locate them, especially when they differ from debug to release mode. 找到它们总是很困难,特别是当它们从调试模式到发布模式不同时。

On the other hand, since you are using C++ , you could get away by using a std::string instead of a manually allocated buffer >> there is a reason for which RAII exists ;) 另一方面,由于您使用的是C++ ,您可以通过使用std::string而不是手动分配的缓冲区来逃避>>存在RAII存在的原因;)

One type of problem I had when I observed this symptom is that I had a multi-process program crash on me when run in shell, but ran flawlessly when called from valgrind or gdb . 我观察到这种症状时遇到的一种问题是,当我在shell中运行时,我遇到了一个多进程程序崩溃,但是当从valgrindgdb调用时,它运行得很完美。 I discovered (much to my embarrassment), that I had a few stray processes of the same program still running in the system, causing a mq_send() call to return with error. 我发现(很多我的尴尬),我在系统中仍然运行了一些相同程序的杂散进程,导致mq_send()调用返回错误。 The problem was that those stray processes were also assigned the message queue handle by the kernel/system and so the mq_send() in my newly spawned process(es) failed, but undeterministically (per the kernel scheduling circumstances). 问题是这些杂散进程也被内核/系统分配了消息队列句柄,因此我新生成的进程中的mq_send() )失败,但不确定(根据内核调度情况)。

Like I said, trivial, but until you find it out, you'll tear your hair out! 就像我说的那样,琐碎,但直到你发现它,你才会把你的头发撕掉!

I learnt from this hard lesson, and my Makefile these days has all the appropriate commands to create a new build, and cleanup the old environment (including tearing down old message queues and shared memory and semaphores and such). 我从这个艰难的课程中学到了,现在我的Makefile有了所有适当的命令来创建新的构建,并清理旧的环境(包括拆除旧的消息队列和共享内存和信号量等)。 This way, I don't forget to do something and have to get heartburn over a seemingly difficult (but clearly trivially solvable) problem. 通过这种方式,我不会忘记做一些事情,并且必须对看似困难(但显然是可以解决的)问题感到焦虑。 Here is a cut-and-paste from my latest project: 这是我最新项目的剪切和粘贴:

[Makefile]
all:
      ...
...

obj:
      ...
clean:
      ...
prep:
  @echo "\n!! ATTENTION !!!\n\n"
  @echo "First: Create and mount mqueues onto /dev/mqueue (Change for non ubuntu)"
  rm -rf /run/shm/*Pool /run/shm/sem.*;
  rm -rf /dev/mqueue/Test;
  rm -rf /dev/mqueue/*Task;
  killall multiProcessProject || true;

These two are the first two lines in their function. 这两个是它们功能中的前两行。

If you really mean that the way I interpret it, then the first line is declaring a local variable buf in one function, but the delete is deleting some different buf declared outside the second function. 如果你的意思是我解释它的方式,那么第一行是在一个函数中声明一个局部变量buf,但删除是删除在第二个函数之外声明的一些不同的buf。

Maybe you should show the two functions. 也许你应该展示这两个功能。

Have you tried simply isolating this with the same build file but code based just on what you've put above? 您是否曾尝试使用相同的构建文件将其隔离,但仅根据您上面的内容编写代码? Something like: 就像是:

int main(int argc, char* argv[] )
{
    const int len( 16 );
    char* buf = new char[len + 1]; 

    delete [] buf;
}

The code you've given is absolutely fine and, on it's own, should run with no problems either in debug or optimised. 您给出的代码绝对正常,并且在它自己的代码中,应该在调试或优化时运行没有任何问题。 So if the problem isn't down to specifics of your code, then it must be down to specifics of the project (ie compilation / linkage) 因此,如果问题不在于您的代码的具体细节,那么它必须归结为项目的细节(即编译/链接)

Have you tried creating a brand new project and placing the 10K+ lines of C++ into it? 您是否尝试过创建一个全新的项目并将10K + C ++行放入其中? Might not take too long to prove the point. 可能不需要太长时间来证明这一点。 Especially if the existing project has either been imported in or heavily altered. 特别是如果现有项目已经导入或严重改变。

It sounds like you have an unitialised variable somewhere in the code. 听起来你在代码中的某个地方有一个整体变量。

In debug mode all the memory is initialised to somthing standard so you will get consistant behavior. 在调试模式下,所有内存都初始化为标准,因此您将获得一致的行为。

In release mode the memory is not initialised unless you explicitly do somthing. 在释放模式下,除非您明确地执行某些操作,否则不会初始化内存。

Run your compiler with the warnings set at the highest level possable. 使用最高级别设置的警告运行编译器。
Then make sure you code compiles with no warnings. 然后确保代码编译没有警告。

I was having the same issue, and I figured out that my program was only crashing when I went to delete[] char pointers with a string length of 1. 我遇到了同样的问题,我发现当我去删除字符串长度为1的[]字符串指针时,我的程序才崩溃。

void DeleteCharArray(char* array){
 if(strlen(array)>1){delete [] array;}
 else{delete array;}
}

This fixed the issue, but it is still error prone, but could be modified to be otherwise. 这解决了这个问题,但它仍然容易出错,但可以修改为其他方式。 Anyhow the reason this happens I suspect is that to C++ char* str=new char[1] and char* str=new char; 无论如何,我怀疑这是因为C ++ char * str = new char [1]char * str = new char; are the same thing, and that means that when you're trying to delete a pointer with delete[] which is made for arrays only then results are unexpected, and often fatal. 是同一个东西,这意味着当你试图删除一个只有数组的delete []时 ,结果是意外的,而且往往是致命的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 VS程序在调试而不是发布模式下崩溃? - VS program crashes in debug but not release mode? Directshow渲染过滤器仅在发布模式下崩溃 - Directshow render filter crashes only in release mode SFML 2.1程序在调试模式下运行良好,但在发布模式下崩溃 - SFML 2.1 program runs fine in debug mode, but crashes in release mode 程序仅在发布版本时崩溃——如何调试? - Program only crashes as release build — how to debug? QT Creator:程序在调试模式下崩溃,但在发布模式和调试模式下工作,带有基于QThread的程序的断点 - QT Creator : Program crashes in debug mode but working in Release mode and in DEBUG Mode with breakpoints for QThread based program 我的C ++应用程序仅在发布模式和Windows 7中崩溃 - My C++ App Crashes Only in Release Mode and Windows 7 在调试器模式下工作。 在可执行模式下崩溃 - works in debugger mode. Crashes in executable mode 在发布模式下运行程序 - running the program in the Release mode 程序使用“windows 本地调试器”运行,但在以发布或调试模式构建后运行 .exe 文件时不运行 - Program runs with 'windows local debugger' but not when running the .exe file after building in either release or debug mode 为什么不正确的 memory 分配给缓冲区只会在发布模式而不是调试模式下编译时导致崩溃? - Why would an incorrect memory allocation to a buffer only cause crashes when compiled in Release mode and not in Debug mode?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM