簡體   English   中英

如果獨立運行,gdb下Linux上的C代碼運行方式是否不同?

[英]C code on Linux under gdb runs differently if run standalone?

我已經使用代碼存儲工具鏈在Linux(Fedora)上構建了普通的C代碼。 這是針對ARM Cortex-A8目標的。 該代碼在運行嵌入式Linux的Cortex A8板上運行。

當我針對某些測試用例運行此代碼時,該測試用例會為較大的大小(10MB)執行動態內存分配( malloc ),經過一段時間后它崩潰,並給出錯誤消息,如下所示:

select 1 (init), adj 0, size 61, to kill
select 1030 (syslogd), adj 0, size 64, to kill
select 1032 (klogd), adj 0, size 74, to kill
select 1227 (bash), adj 0, size 378, to kill
select 1254 (ppp), adj 0, size 1069, to kill
select 1255 (TheoraDec_Corte), adj 0, size 1159, to kill
send sigkill to 1255 (TheoraDec_Corte), adj 0, size 1159
Program terminated with signal SIGKILL, Killed.

然后,當我使用為目標構建的gdb在相同的測試用例上調試此代碼時,即發生這種動態內存分配的時刻,代碼無法分配該內存,並且malloc返回NULL 但是在正常的獨立運行期間,我相信malloc應該分配失敗,但是奇怪的是它可能不會返回NULL ,但是它崩潰了,操作系統殺死了我的進程。

  1. 為什么在gdb下運行和沒有調試器時這種行為不同?
  2. 為什么malloc失敗卻沒有返回NULL 這可能嗎,還是我收到錯誤消息的原因是其他?
  3. 我該如何解決?

謝謝,

-廣告

因此,對於問題的這一部分,有一個肯定的答案:

為什么malloc失敗卻沒有返回NULL。 這可能嗎,還是我收到錯誤消息的原因是其他?

在Linux中,默認情況下,用於分配內存的內核接口幾乎永遠不會完全失敗。 取而代之的是,它們以如下方式設置您的頁表:在首次訪問您要訪問的內存時,CPU將生成一個頁面錯誤 ,此時內核將處理該錯誤並尋找將用於該操作的物理內存。 (虛擬)頁面。 is when the allocation actually fails, killing your process. 因此,在內存不足的情況下,您可以向內核請求內存,它將“成功”,並且當您第一次嘗試觸摸該內存時,它又返回了, 是當分配實際上失敗時,終止了進程。 (或者也許是其他不幸的受害者。對此有一些啟發式方法,我對此並不十分熟悉。請參閱“ oom-killer ”。)

您的其他一些問題,對我來說答案還不太清楚。

為什么在gdb下運行和沒有調試器時這種行為不同?
GDB有自己的malloc並可能以某種方式跟蹤您的分配(可能只是一個猜測)。 在某種程度上相關的一點上,我實際上經常發現我的代碼中的堆錯誤通常無法在調試器下重現。 這令人沮喪,使我撓頭,但這基本上是我已經意識到必須忍受的東西...

我該如何解決?

processes rather than just your own, and it's generally not a good idea to have your program alter global state like that), but you can write the string 2 to /proc/sys/vm/overcommit_memory . 這有點像大錘解決方案(也就是說,它會更改進程的行為,而不僅僅是您自己的行為,通常不希望這樣改變程序的全局狀態),但是您可以編寫字符串2/proc/sys/vm/overcommit_memory 請參閱我從Google搜索獲得的此鏈接

失敗了...我只是確保您分配的資源不超出您的預期。

根據定義,在調試器下運行與獨立運行不同。 調試器可以並且確實隱藏了許多錯誤。 如果要進行調試編譯,則可以添加大量代碼,類似於完全未優化的編譯(例如,允許您單步執行或觀察變量)。 在進行發布的編譯可以刪除調試選項並刪除所需代碼的地方,您可以使用許多優化陷阱。 從您的帖子中我不知道誰在控制編譯選項或它們是什么。

除非您打算交付要在調試器下運行的產品,否則應該獨立進行測試。 理想情況下,您也無需調試器即可進行開發,從而使您不必重復兩次。

這聽起來像是您的代碼中的錯誤,就像用新的眼睛慢慢地重新閱讀代碼一樣,就像是在向某人解釋,或者實際上是在逐行向某人解釋。 可能有些東西您看不到,因為您已經用相同的方式看了太久了。 令人驚訝的是,它運行了多少次,效果如何。

我也可能是編譯器錯誤。 進行輸出返回值之類的操作會導致編譯器生成不同的代碼。 添加另一個變量並將結果保存到該變量可以使編譯器執行其他操作。 嘗試更改編譯器選項,減少或刪除任何優化選項,減少或刪除調試器的編譯器選項,等等。

這是經過驗證的系統,還是您正在開發新硬件? 例如,嘗試在未啟用任何緩存的情況下運行。 在調試器中工作而不是獨立工作,如果不是編譯器錯誤可能是一個計時問題,則單步執行即可沖洗管線,以不同的方式混合緩存,使緩存和內存系統無窮無盡地得到結果實時。

簡而言之,在調試器下運行為什么會隱藏直到在最終可交付結果之類的環境中進行測試之前才發現的錯誤的原因有很長的原因,我只涉及了一些。 讓它在調試器中而不是獨立運行並不奇怪,這只是工具的工作方式。 根據您到目前為止給出的描述,您的代碼,硬件或工具很有可能會出現。

消除它作為代碼或工具的最快方法是反匯編該部分,並檢查如何處理傳遞的值和返回值。 如果返回值得到優化,那么您會找到答案。

您要為共享的C庫還是靜態庫進行編譯? 也許編譯為靜態...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM