我們都知道
bss段需要初始化,但是這是為什麼呢?
通過瀏覽資料,我們都會發現,
bss*.bin *.hex
)中的,因為全都是
0bss
bss段(一堆
0)將來真正執行程式的時候,再根據這兩個資料進行
bss段的初始化就行了。
以上這段文字是網上的資料說的。但是,我可不可以讓
bssnandflash
)拷貝到記憶體中時,捎帶著會把
bss段像
data
段那樣初始化。
實際上是可以這樣做的。請看下邊的兩個鏈結指令碼。
sections
. =
0x30000000;
.text : at(
4096)
.rodata align(
4) : at((loadaddr(.text)+sizeof(.text)+
3)&~(
0x03))
.data align(
4) : at((loadaddr(.rodata)+sizeof(.rodata)+
3)&~(
0x03))
__bss_start = .;
.bss align(
4) :
__bss_end = .;
}
sections
. =
0x30000000;
.text : at(
4096)
.rodata align(
4) : at((loadaddr(.text)+sizeof(.text)+
3)&~(
0x03))
.bss align(
4) : at((loadaddr(.rodata)+sizeof(.rodata)+
3)&~(
0x03))
.data align(
4) : at((loadaddr(.bss)+sizeof(.bss)+
3)&~(
0x03))
}
鏈結指令碼一,把
bss段放在最後邊,
arm-linux-gcc
編譯器預設的會把
bss段給忽略掉,也即不會讓
bss這種鏈結指令碼也是我們通常見到的方式。
鏈結指令碼二,把
bss段放在了
rodata
段和data
段中間,這個時候,
arm-linux-gcc
編譯器並不會把
bssbss
rodata
段、bss
段、data
段是連續的,也即程式執行時這幾個段是連續的;倘若把
bssrodata
段後邊緊接著的是
data
段;這就要求程式的這兩個段需要分別處理,而不能一次性將它們連續拷貝過去。
鏈結指令碼二的方法可以讓
bssbss
bss段,所以必須在應用程式執行前,根據
bss段的起始位址和結束位址將
bss段初始化。
下邊,著重講一下鏈結指令碼中與初始化
bss段相關的幾句話。 (
1) __bss_start = .;
(2).bss align(
4) :
(3)__bss_end = .;
這裡,實際上句(
1)是在
bss段的起始位址處定義了乙個
int型別的全域性變數
__bss_start
。雖然,
bss段的起始位址處肯定是乙個未初始化的全域性變數,但是這裡算是編譯器又在這個位置上又重新定義了乙個全域性變數。就是說,乙個位址有兩個名字,它們都能訪問這個位址空間。句(
3)的解釋同句(1)。
接著我們再看一下用
c語言寫的初始化
bss段的程式。
( 1)
void clean_bss(
void)
(2)
首先,句(3
)對編譯器產生的兩個全域性變數進行宣告。句(
4)通過
__bss_start
取出bss
段的起始位址,句(
6)通過
__bss_end
取出bss
段的結束位址。
C 為什麼需要成員初始化列表
將建構函式分為兩個階段的執行過程 初始化階段和建構函式函式體階段。既然稱它為成員初始化列表,那麼該階段在初始化階段完成。那麼類成員變數不外乎類型別和非類型別。而對於非類型別而言,此時 無論是在初始化表中還是函式體內完成賦值效果是一致的,即並未初始化。表現的有點不同的是類型別 test1 includ...
使用HashMap時為什麼需要設定初始化大小
hashmap有擴容機制,就是當達到擴容條件時會進行擴容。hashmap的擴容條件就是當hashmap中的元素個數 size 超過臨界值 threshold 時就會自動擴容。在hashmap中,threshold loadfactor capacity。所以,如果我們沒有設定初始容量大小,隨著元素的...
什麼時候需要初始化列表?
在剛接觸qt的時候我們都會看到自動生成的主介面建構函式如下 mainwidget mainwidget qwidget parent qwidget parent ui new ui mainwidget 這邊使用的就是初始化列表,初始化列表主要用於以下幾種情況 第一種 類b中包含另乙個類a的物件a...