2010-11-10 54 views
3

我正在爲c編寫一個Atmel XMEGA微控制器的固件,我想我填充了4 KB的SRAM。據我所知,我只有靜態/全局數據和本地堆棧變量(我在我的代碼中使用malloc)。我如何知道我的記憶是否已滿?

我使用本地變量緩衝一些像素數據。如果我將緩衝區增加到51字節,我的顯示器顯示出奇怪的結果 - 一個6字節的緩衝區運行良好。這就是爲什麼我認爲我的內存已滿並且堆棧覆蓋了某些內容。

創建更多的空閒內存是而不是我的問題,因爲我可以將一些靜態數據移動到閃存中,只在需要時才加載它。令我困擾的是,我從未發現記憶已滿。

當內存被填滿而不是讓它覆蓋其他數據時,是否有可能發現(例如,通過重置微控制器)?

回答

3

要準確預測需要多少堆棧可能非常困難(如果打開正確的選項,某些工具鏈可能會遇到問題,但這只是一個粗略的指導)。

檢查堆棧狀態的常用方法是在啓動時用完全已知的值填充堆棧,儘可能難以運行代碼,然後查看未覆蓋多少堆棧。

您的工具鏈的啓動代碼甚至可能會有一個選項爲您填充堆棧。不幸的是,雖然這些概念非常簡單:用已知的值填充堆棧,計算剩餘的值的數量,但實現它的實際可能需要深入理解特定工具(特別是啓動代碼和鏈接器)工作。

粗略的方法來檢查堆棧溢出是什麼導致您的問題是使所有本地數組「靜態」和/或大幅度增加堆棧的大小,然後看看事情是否更好。這些在小型嵌入式系統上都很難做到。

0

通常你的編程工具知道控制器的參數,所以如果你使用更多(沒有mallocs,它在編譯時已知)應該被警告。

但是你應該小心pixeldata,因爲大多數顯示器沒有線性地址空間。

編輯:通常你可以手動指定堆棧大小。留下足夠的內存用於靜態變量,並保留其餘的堆棧。

+0

據我所知,局部變量確實存在於堆棧中。但是堆棧的大小在編譯時還不知道,還是我錯了? – Martin 2010-11-10 09:41:52

+0

@Martin:如果你不使用遞歸和變量大小的局部變量(字母只允許一些C編譯器),則可以在編譯時知道棧的大小。 – Curd 2010-11-10 09:56:23

1

「是它在某種程度上可能dected(由正在重置微控制器例如 )時 內存得到了填補,而不是 讓它覆蓋其他一些數據?」

我想現在你有一個內存映射像(1)。 當堆棧和/或變量空間增長很多時,它們會相互衝突並相互覆蓋(*)。

另一種可能性是類似於(2)的存儲器映射。 當堆棧或變量空間超過最大空間時,它們會遇到未映射的addr空間(*)。 根據控制器(我不確定AVR家族),這會導致重置/陷阱或類似(=您所期望的)。

[not mapped addr space][ RAM mapped addr space ][not mapped addr space] 
(1)      [variables ---> * <--- stack] 
(2)      *[ <--- stack variables ---> ]* 

(箭頭表示生長方向,如果使用更多的變量/堆棧)

當然最好是要確保事前即RAM足夠大。

1

通常,鏈接器負責爲代碼,常量,靜態數據,堆棧和堆分配內存。通常你必須指定所需的堆棧大小(和可用內存)給鏈接器,如果它不適合所有東西,它將會標記一個錯誤。

還要注意,如果你正在處理多線程應用程序,那麼每個線程有它自己的堆棧,並且這些經常在線程啓動時從堆中分配。

除非你的處理器有一些硬件檢查堆棧溢出(不太可能),你可以使用一些技巧來監視堆棧的使用情況。

  • 用已知的標記模式填充堆棧,並檢查堆棧內存(由鏈接器分配)以確定標記的多少未被破壞。
  • 在一個定時器中斷(或類似)比較與所述堆疊的底部的主線程堆棧指針以檢查溢出

這兩種方法都在調試是有用的,但它們不能保證捕捉所有問題,並且通常只會在堆棧已經損壞其他東西之後標記問題...

相關問題