2012-03-01 85 views
3

我目前正在調試一個相當大的程序。當我來到下面的代碼行時:字符串故障

value->binary_string = value_it->binary_string.substr(range->msb->value, range->size); 

該程序行爲不正確。這裏value是一個指向具有類型爲std :: string的成員名爲binary_string的結構體的指針。當我到達這條線在調試時,我看到:

value_it->binary_string = "00000000000000000000000000000111" 
range->msb->value = 0 
range->size = 32 

後這行代碼執行時,值 - > binary_string是空的!我甚至已經改變了行

value->binary_string = value_it->binary_string 

,它仍然失敗!

當我在調試時到達這條線時,我的程序使用了大約100 Mb的內存,所以我不認爲這是內存問題(儘管我正在運行Valgrind,因爲我們正在驗證這一點)。我使用Ubuntu 11.10,g ++ - 4.6和libstdC++ 6。

有沒有人遇到過這樣的事情?我不知道爲什麼我的琴絃不工作!

感謝,

山姆

EDIT1:

類型的值NumberInst,定義如下:

typedef std::string String; 

struct NumberInst 
{ 
    unsigned size; 
    bool signed_; 
    String binary_string; 
    bool valid; 
    unsigned value; 

    NumberInst(); 
}; 

EDIT2:

它看起來像我已經一點點縮小搜索範圍。在調試時,我嘗試了幾條打印命令:

print value_it->binary_string 
"00000000000000000000000000000111" 
print value_it->binary_string[31] 
'1' 
print value_it->binary_string.substr(0, String::npos) 
"" 
print value_it->binary_string.substr(0, 1) 
"" 

看來substr在這種情況下工作不正常。但是,當我在主函數中測試substr時,它似乎工作正常。

+0

您驗證了'value'分配正確(並且沒有被釋放)嗎? – Yaniro 2012-03-01 21:35:08

+0

@Yaniro我剛查過。新的調用就在這行代碼之前,當我進入新的調用時,我到達構造函數的值。另外,我測試了一個push_back的調用,這似乎正常工作。 – 2012-03-01 21:41:12

+0

看看這個副本寫的東西:http://en.wikipedia.org/wiki/Copy-on-write ...它可能是兩個字符串使用相同的緩衝區,直到你改變其中一個,如果我理解正確... – Yaniro 2012-03-01 21:47:51

回答

1

問題是由一個非常微妙的錯誤引起的。某處在我的項目:

NumberInst* number = new NumberInst; 
number->binary_string.reserve(size); 
for (unsigned i = 0; i < size; i++) 
    number->binary_string[i] = ...; 

因爲我假定標準庫的一個std :: out_of_range異常不會被拋出相比之下,字符串的能力(而不是字符串的大小)的數組索引。在調試器中調用打印將會成功,因爲它可能遍歷緩衝區,直到達到'\ 0'字符。然而

String str = number->binary_string 

將會失敗,因爲它是可能的標準庫的副本value_it-的緩衝>從[0,大小)binary_string並增加了一個「\ 0」字符。由於value_it-> binary_string的大小爲0,所以複製其內容將失敗(substr和其他函數依賴於調用字符串的大小)。

換句話說,這個問題是通過調用

str.reserve(size); 

,而不是

str.resize(size); 

感謝您的幫助大家造成的!

山姆

+0

'NumberInst * number = new NumberInst;'此代碼可能不會做你認爲的事情。我建議在構造函數後總是提到括號,除非你現在真的在做你正在做的事情。當然,建議儘可能創建值。 – 2012-03-03 10:39:49

2

我發現,通常有這樣當「奇怪」的事情發生了兩種常見的原因:

  1. 你犯了一個簡單的錯誤,並只是俯瞰它。
  2. 某種形式的內存損壞。

要檢查第一個原因,請仔細閱讀有問題的代碼,並有意識地決定閱讀代碼正在做什麼,而不是您認爲應該做什麼。通過假設代碼應該做某件事實際上沒有的東西,尤其是在你一直在看的代碼中,忽略明顯的錯誤是很容易的。例如,幾個月前我正在調試一些東西,並且突然出現一個變量「神奇地」改變其值的問題。原來,我只是打印了一個錯誤的變量(呵呵!),如果我一直在閱讀代碼的實際內容,我會盡早發現它。

內存損壞是一個更難找到的動物,因爲它可能發生在任何時候運行的任何代碼之前,當問題出現時。 Valgrind並不保證找到所有形式的腐敗,例如this question。在調試模式下運行,設置內存觀察點(如果你知道腐敗總是在哪裏發生的話)和其他內存相關的工具可能會有所幫助,同樣可以將問題簡化爲最小化的形式......保持消除代碼運行一點點,直到腐敗沒有發生。

+0

我喜歡這個回答。你會看到爲什麼我發佈了我的答案後:) – 2012-03-01 23:04:33

+0

我不能回答我自己的問題另外六個小時... – 2012-03-01 23:20:20