2015-09-02 37 views
0

我打電話從python腳本(OS的Ubuntu 14.04)一個C++應用:瞭解像這樣的「雙重釋放或腐敗」的錯誤

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) 

然後我收到以下錯誤消息(儘管該地址是不同的每時間):

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

該應用程序本身是第三方二進制文件,也就是說,我無法訪問源代碼。然而,即使是在暗示存在app一些錯誤會導致刪除嘗試相同的實體兩次有3個strangenesses的行爲,我無法理解:

  1. 隨機相當罕見出現的錯誤(約20%全部運行在相同的數據上)。 app的一些其他用戶也會收到此錯誤;然而,其中一些人從來沒有得到它。
  2. 它不會被子流程的stderr流捕獲(因此sys.exit(1)未得到執行)。
  3. 有時我會在括號中看到top而不是!prev

有人可以解釋我,這些功能是如何起源的,甚至可以給出一個示例C++代碼來重現此行爲?

+2

那麼,很明顯,錯誤是在你沒有發佈的代碼中。雙倍免費意味着你兩次釋放同樣的東西,例如'int * p = new int;刪除p;刪除p;' – Barry

+2

至於*沒有出現在'stderr' *:gcc(並且可能是glibc)[直接打開'/ dev/tty'](http://stackoverflow.com/questions/31301711/how-can- a-unix-program-display-on-screen-even-when-stdout-and-stderr -31302382#31302382)輸出繞過IO重定向的致命錯誤。 – dhke

回答

3

雙人自由到底是什麼意思:

int *a = new int; 
delete a; 
delete a; 

腐敗是這樣的:

int *a = new int[10]; 
a++; 
delete a; 

由glibc的生成此消息時,應用程序請求釋放已被釋放一些內存,或者地址不對應於在分配時獲得的地址。

+0

在這種情況下,我會永久觀察錯誤並且不時** – Roman

+3

@Roman這樣做的問題是,當發生雙重空閒時,行爲是不確定的。因此沒有人能保證能夠重現問題的代碼。例如,如果指針爲NULL,則釋放這樣的值是完全可以的。但是,如果由於某種原因指針不是NULL,那麼這無疑是一個錯誤,從而增加了它被報告的機會。 – PaulMcKenzie

+0

@Roman這是一個雙免費的例子(這正是你所要求的嗎?),但是這種類型的代碼可以嵌入一個複雜的條件/循環結構中,有時候這些條件/循環都是真的,有時甚至不是,這取決於上下文。 –

相關問題