理解“双重释放或损坏”错误

Rom*_*man 1 c++ memory

我正在C++python脚本(OS Ubuntu 14.04)调用应用程序,如下所示:

import sys, subprocess
run = subprocess.Popen(['app'] + args, stdout = subprocess.PIPE,
                       stderr = subprocess.PIPE)
stdout, stderr = run.communicate()
if stderr:
    sys.stderr.write('Error in app: ' + stderr.decode('utf-8'))
    sys.exit(1)
Run Code Online (Sandbox Code Playgroud)

然后我得到以下错误信息(虽然地址每次都不一样):

*** Error in `/usr/bin/app': double free or corruption (!prev): 0x00007f50eae98070 ***
Run Code Online (Sandbox Code Playgroud)

该应用程序本身是第三方二进制文件,这意味着我无法访问源代码。但是,即使建议存在一些错误app,导致删除尝试两次相同的实体,但我无法理解的行为中有 3 个奇怪之处:

  1. 该错误是随机发生的,而且相当罕见(大约 20% 的运行在相同的数据上)。其他一些用户app也会收到此错误;然而,他们中的一些人永远不会得到它。
  2. 它不会stderr被子进程的流捕获(因此sys.exit(1)不会被执行)。
  3. 有时我看到top而不是!prev在括号中。

有人可以解释一下,这些功能是如何产生的,甚至可以给出一个重现这种行为的示例 C++ 代码吗?

Jea*_*nès 7

双免费正是它的意思:

int *a = new int;
delete a;
delete a;
Run Code Online (Sandbox Code Playgroud)

对于腐败,例如:

int *a = new int[10];
a++;
delete a;
Run Code Online (Sandbox Code Playgroud)

当应用程序请求释放一些已经释放的内存,或者地址与分配时获得的地址不对应时,glibc 会生成此消息。

  • @Roman 问题在于,当发生双重释放时,行为未定义。因此,没有人可以保证重现该问题的代码。例如,如果指针为 NULL,则双重释放这样的值是完全可以的。但是如果由于某种原因该指针不是 NULL,那么这无疑是一个错误,从而增加了它被报告的机会。 (3认同)