2009-05-27 33 views
3

這讓我感到非常緊張。我剛剛第一次將我的第一個應用程序上傳到App Store,當然,現在我的應用程序正在左右爆炸。當我使用發佈版本配置構建時,我在應用程序上敲擊了一段時間後隨機獲得EXC_BAD_ACCESS。我重新打開殭屍,但問題似乎沒有過度釋放一個變量,因爲我沒有收到關於向釋放變量發送消息的消息。EXC_BAD_ACCESS,但沒有殭屍,也沒有在調試版本配置中

該錯誤總是出現在我的代碼中的相同位置。它看起來像我試圖保留一個尚未正確初始化的變量。我沒有絲毫的想法,我該怎麼做。

但是,這裏有一個奇怪的事情:如果我構建調試版本配置,它永遠不會崩潰。我可以整天砰砰作響,它堅如磐石。我使用Release配置進行構建,並且它會間歇性地崩潰。

查看兩種配置中的「生成」設置,沒有太多差異。在調試中,GCC 4.0優化級別是「無」,而在Release中,它是「最快,最小」。如果我將Release中的優化級別切換爲「無」,則該應用會自行運行。有沒有人有線索我應該尋找解決這個問題?或者,如果我沒有優化分配,會發生多少不好的事情?

UPDATE:

黨!我真的需要一個神奇的調試工具來處理內存錯誤。我在最後一天左右一直在處理這個問題。我添加了一個exercise方法,可以可靠地生成崩潰並開始尋找導致它的代碼區域。

該應用程序通常會在第3-5次崩潰時執行一種特定類型的操作。這種類型的操作唯一不同的是我從附件方法返回的價值。配件方法通常返回NSDecimalNumber s值爲0-3,但是當我返回一個非整數值的NSDecimalNumber時有一個特殊情況。我會測試附件方法尋找非整數值的結果。我改變了特殊情況,返回值爲-1的NSDecimalNumber而不是非整數值,我不能再讓應用崩潰。

基本上,我所做的唯一的變化是從 [[NSNumber numberWithDouble:num] decimalValue]開關 - >崩潰 到 [[NSNumber numberWithInteger:num] decimalValue] - >沒有崩潰

這一點,但比這更復雜一些,但並不多。

現在,我很高興該應用程序不再崩潰,但我所做的更改並不能滿足我的信心,因爲舊代碼不會以任何方式「破碎」。所以,雖然我的應用程序不再崩潰,但並不是因爲我「修復」了它,而是隨機更改了一些東西,現在它可以正常工作。 8 ^(

UPDATE:

調試器不吐堆棧跟蹤,因爲它通常在程序崩潰時崩潰,所述調試控制檯輸出以下的作用:。

加載程序到調試器...

[...版權所有...]

This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found). 

warning: Unable to read symbols from "UIKit" (not yet mapped into memory). 

warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found). 

warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory). 
Program loaded. 

sharedlibrary apply-load-rules all 

Attaching to program: `/Users/...', process 10066. 

Re-enabling shared library breakpoint 1 

Cannot access memory at address 0x4 

Cannot access memory at address 0x4 

(gdb) 
+0

你應該看看你的堆棧跟蹤。什麼是真正的崩潰?更改NSNumber導致崩潰的事實表明,您可能會在某處過度釋放NSNumber。 NSNumbers由類緩存;如果您過度釋放一個,您可以崩潰在代表相同數字的完全不同的對象上。我看到代碼在值爲2時工作,但在4時失敗,因爲「4」的NSNumber在系統中的其他地方被過度釋放。 – 2009-05-28 03:53:04

+0

我在調試這個問題時遇到了一些問題。由於我不明白的原因,調試器和樂器都沒有給我提供我期望的信息。通常,當應用程序崩潰時,調試器只顯示主執行線程,沒有關於誰調用導致崩潰的方法的詳細信息。也許這是因爲問題只在編譯器優化代碼時才顯現出來,所以調試器將源代碼映射到目標代碼的時間更加困難。我相信它也不能幫助我的調試排序仍然有點根本。一如既往,我感謝您的協助。 – ChadK 2009-05-28 05:19:09

+0

不過,您應該發佈堆棧跟蹤(特別是前幾幀)。即使它不包含任何代碼,它也可以提供有關問題出處的很多信息。在Cocoa,你經常會要求代表你在稍後時間以你的名義運行。 -autorelease是一個很常見的例子。當「稍後時間」崩潰時,沒有任何「代碼」會出現在堆棧中,但仍然是由於代碼中的錯誤。 – 2009-05-28 13:30:59

回答

2

如果只有它是作爲開啓殭屍一樣方便,你總是可以找到你過發佈...有很多這類殭屍無法檢測到的錯誤的。對於內存錯誤沒有神奇的調試工具;只有謹慎的編程(並且有一些模式使得這些錯誤更加罕見,並且在它們確實發生時更容易調試)。

優化後的代碼可以免費使用大量未經優化代碼顯示的內容。它確實表明它可能是一個局部變量而不是一個伊娃,但可能不是。它可能只是時機;更快的速度可能會使比賽條件更頻繁地走向另一條路。

如果你可以讓它崩潰,當然作爲第一步看看堆棧跟蹤。

沒有優化分配沒有什麼大錯,但它只是掩蓋了問題。那裏有一個編碼錯誤。優化不會破壞你的代碼。您的代碼已損壞。

有關調試內存問題的一個很好的討論here。 #1規則是你必須使用訪問器。他們會爲你節省很多心痛,所以希望你已經做到了。我在memory management rules的簡短討論中提供了其他一些指標。

1

我建議在編譯器上啓動警告級別,看看是否有任何東西彈出。打開您的項目設置並啓用您可以找到的每個「警告」選項。或者,找到名稱爲的項目設置其它C標誌並添加標記-Wall -Wextra

對於像有符號/無符號不匹配,可能的精度損失等問題,您可能會(通常)安全地忽略,您將會得到很多白噪聲。但是,可能會出現一些重要的警告,您絕對不應該忽略這些警告:例如在沒有投射的情況下從整數形成指針(反之亦然)。如果您不是100%確定可以忽略該警告,請修復代碼以避免警告消失。

相關問題