⑴ c語言:內存分哪幾個區各有什麼用
32位操作系統中有4G的虛擬內存,1、os區為系統所佔內存 2、棧區auto區的內存是自動分配的,不需要malloc申請 3、堆區需要自己申請所要用的內存,在用的同時,用完之後要用free釋放,防止內存泄漏 4、靜態區分中有BSS區.文本區.常量區
⑵ 分析下面程序,指出其中變數是屬於棧堆還是數據段,bss段
5個數據段
進程(執行的程序)會佔用一定數量的內存,它或是用來存放從磁碟載入的程序代碼,或是存放取自用戶輸入的數據等等。不過進程對這些內存的管理方式因內存用途 不一而不盡相同,有些內存是事先靜態分配和統一回收的,而有些卻是按需要動態分配和回收的。對任何一個普通進程來講,它都會涉及到5種不同的數據段。
Linux進程的五個段
下面我們來簡單歸納一下進程對應的內存空間中所包含的5種不同的數據區都是干什麼的。
BSS段:BSS段(bss segment)通常是指用來存放程序中未初始化的全局變數的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。
數據段:數據段(data segment)通常是指用來存放程序中已初始化的全局變數的一塊內存區域。數據段屬於靜態內存分配。
代碼段:代碼段(code segment/text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變數,例如字元串常量等。
堆(heap):堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)
棧(stack):棧又稱堆棧, 是用戶存放程序臨時創建的局部變數,也就是說我們函數括弧「{}」中定義的變數(但不包括static聲明的變數,static意味著在數據段中存放變數)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進後出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。
它是由操作系統分配的,內存的申請與回收都由OS管理。
PS:
全局的未初始化變數存在於.bss段中,具體體現為一個佔位符;全局的已初始化變數存於.data段中;而函數內的自動變數都在棧上分配空間。.bss是不佔用.exe文件空間的,其內容由操作系統初始化(清零);而.data卻需要佔用,其內容由程序初始化,因此造成了上述情況。
bss段(未手動初始化的數據)並不給該段的數據分配空間,只是記錄數據所需空間的大小。
data(已手動初始化的數據)段則為數據分配空間,數據保存在目標文件中。 數據段包含經過初始化的全局變數以及它們的值。BSS段的大小從可執行文件中得到 ,然後鏈接器得到這個大小的內存塊,緊跟在數據段後面。當這個內存區進入程序的地址空間後全部清零。包含數據段和BSS段的整個區段此時通常稱為數據區。
⑶ 內核會初始化自己的BSS段為0么
在採用段式內存管理的架構中(比如intel的80x86系統),bss段(Block
Started
by
Symbol
segment)通常是指用來存放程序中未初始化的全局變數的一塊內存區域,一般在初始化時bss
段部分將會清零。bss段屬於靜態內存分配,即程序一開始就將其清零了。
比如,在C語言之類的程序編譯完成之後,已初始化的全局變數保存在.data
段中,未初始化的或初始化為0全局變數保存在.bss
段中。
⑷ C語言之變數作用域
全局變數:作用域整個工程,在使用的地方通過extern聲明即可,存放於全局數據區,佔用靜態存儲單元。
局部變數:作用於函數方法體內,函數執行結束就釋放,存放於棧區。
全局靜態變數:作用於當前類,在外部類不可使用,除非使用#include引入頭文件,存放於全局數據區。
局部靜態變數:作用於函數方法體內,函數執行結束不釋放,存放於全局數據區。
全局靜態存儲區:分為 DATA 段和 BSS 段。DATA 段(全局初始化區)存放初始化的全局變數和靜態變數;BSS 段(全局未初始化區)存放未初始化的全局變數和靜態變數。程序運行結束時自動釋放。其中BBS段在程序執行之前會被系統自動清0,所以未初始化的全局變數和靜態變數在程序執行之前已經為0。存儲在靜態數據區的變數會在程序剛開始運行時就完成初始化,也是唯一的一次初始化。
靜態存儲變數的優勢:
優勢: 可以節省內存,因為它是所有對象所公有的,因此,對多個對象來說,靜態數據成員只存儲一處,供所有對象共用。靜態數據成員的值對每個對象都是一樣,但它的值是可以更新的。只要對靜態數據成員的值更新一次,保證所有對象存取更新後的相同的值,這樣可以提高時間效率。
關於static
(1)在修飾變數的時候,static 修飾的靜態局部變數只執行初始化一次,而且延長了局部變數的生命周期,直到程序運行結束以後才釋放。
(2)static 修飾全局變數的時候,這個全局變數只能在本文件中訪問,不能在其它文件中訪問,即便是 extern 外部聲明也不可以。
(3)static 修飾一個函數,則這個函數的只能在本文件中調用,不能被其他文件調用。static 修飾的變數存放在全局數據區的靜態變數區,包括全局靜態變數和局部靜態變數,都在全局數據區分配內存。初始化的時候自動初始化為 0。
(4)不想被釋放的時候,可以使用static修飾。比如修飾函數中存放在棧空間的數組。如果不想讓這個數組在函數調用結束釋放可以使用 static 修飾。
(5)考慮到數據安全性(當程序想要使用全局變數的時候應該先考慮使用 static)。
⑸ c語言指針面試常見問題
c語言指針面試常見問題
指針的使用,一直是c語言面試題中必考的部分,因為指針本身使用的復雜性與普適性,所以考點非常多,而且也可以與其他知識相互結合,因此我們將會使用五篇專題的篇幅來介紹指針。
分析下面的程序,指出程序中的錯誤:
本題解析
沒有正確為str分配內存空間,將會發生異常。問題出在將一個字元串復制進一個字元變數指針所指地址。雖然編譯的時候沒有報錯,但是在運行過程中,因為越界訪問了未被分配的內存,而導致段錯誤。
相關知識點
在處理與指針相關的問題時,首先需要搞明白的就是內存,因為指針操作的就是內存。
第一個,就是內存的分區。這也是經常會被考察的一個考點。
寫出內存分為幾大區域
對於這個問題,有幾種不同的說法,有的說內存分為五大分區,有的說分為四大分區,我們先來看五大分區的說法:
認為內存分為五大分區的人,通常會這樣劃分:
1、BSS段( bss segment )
通常是指用來存放程序中未初始化的'全局變數和靜態變數 (這里注意一個問題:一般的書上都會說全局變數和靜態變數是會自動初始化的,那麼哪來的未初始化的變數呢?變數的初始化可以分為顯示初始化和隱式初始化,全局變數和靜態變數如果程序員自己不初始化的話的確也會被初始化,那就是不管什麼類型都初始化為0,這種沒有顯示初始化的就 是我們這里所說的未初始化。既然都是0那麼就沒必要把每個0都存儲起來,從而節省磁碟空間,這是BSS的主要作用)的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。 BSS節不包含任何數據,只是簡單的維護開始和結束的地址,即總大小。以便內存區能在運行時分配並被有效地清零。BSS節在應用程序的二進制映象文件中並不存在,即不佔用 磁碟空間 而只在運行的時候佔用內存空間 ,所以如果全局變數和靜態變數未初始化那麼其可執行文件要小很多。
2、數據段(data segment)
通常是指用來存放程序中已經初始化的全局變數和靜態變數的一塊內存區域。數據段屬於靜態內存分配,可以分為只讀數據段和讀寫數據段。字元串常量等,但一般都是放在只讀數據段中。
3、代碼段(code segment/text segment)
通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變數,例如字元串常量等,但一般都是放在只讀數據段中 。
4、堆(heap)
堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或 縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張); 當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)
5、棧 (stack)
棧又稱堆棧, 是用戶存放程序臨時創建的局部變數,也就是說我們函數括弧「{}」 中定義的變數(但不包括static聲明的變數,static意味著在數據段中存放變 量)。除此以外, 在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值 也會被存放回棧中。由於棧的先進先出特點,所以 棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。
而四大分區的說法,則這么認為:
1、堆區:
由程序員手動申請,手動釋放,若不手動釋放,程序結束後由系統回收,生命周期是整個程序運行期間。使用malloc或者new進行堆的申請,堆的總大小為機器的虛擬內存的大小。
說明:new操作符本質上是使用了malloc進行內存的申請,new和malloc的區別如下:
(1)malloc是C語言中的函數,而new是C++中的操作符。
(2)malloc申請之後返回的類型是void*,而new返回的指針帶有類型。
(3)malloc只負責內存的分配而不會調用類的構造函數,而new不僅會分配內存,而且會自動調用類的構造函數。
2、棧區:
由系統進行內存的管理。主要存放函數的參數以及局部變數。在函數完成執行,系統自行釋放棧區內存,不需要用戶管理。整個程序的棧區的大小可以在編譯器中由用戶自行設定,VS中默認的棧區大小為1M,可通過VS手動更改棧的大小。64bits的Linux默認棧大小為10MB,可通過ulimit -s臨時修改。
3、靜態存儲區:
靜態存儲區內的變數在程序編譯階段已經分配好內存空間並初始化。這塊內存在程序的整個運行期間都存在,它主要存放靜態變數、全局變數和常量。
注意:
(1)這里不區分初始化和未初始化的數據區,是因為靜態存儲區內的變數若不顯示初始化,則編譯器會自動以默認的方式進行初始化,即靜態存儲區內不存在未初始化的變數。
(2)靜態存儲區內的常量分為常變數和字元串常量,一經初始化,不可修改。靜態存儲內的常變數是全局變數,與局部常變數不同,區別在於局部常變數存放於棧,實際可間接通過指針或者引用進行修改,而全局常變數存放於靜態常量區則不可以間接修改。
(3)字元串常量存儲在靜態存儲區的常量區,字元串常量的名稱即為它本身,屬於常變數。
(4)數據區的具體劃分,有利於我們對於變數類型的理解。不同類型的變數存放的區域不同。後面將以實例代碼說明這四種數據區中具體對應的變數。
4、代碼區:
存放程序體的二進制代碼。比如我們寫的函數,都是在代碼區的。
通過上面的不同說法,我們也可以看出,這兩種說法本身沒有優劣之分,具體的內存劃分也跟編譯器有很大的關系,因此這兩種說法都是可以接受的,搞明白內存的分區之後,指針的使用才能夠更加的靈活。
;⑹ BSS是什麼意識
BSS全名為:Base Station Subsystem,GSM網路中的基站子系統模塊 。
WLAN中的BSS:一種特殊的Ad-hoc LAN的應用,稱為Basic Service Set (BSS),一群計算機設定相同的BSS名稱,即可自成一個group,而此BSS名稱,即所謂BSSID。
是「Block Started by Symbol」的縮寫,意為「以符號開始的塊」。
BSS是Unix鏈接器產生的未初始化數據段。其他的段分別是包含程序代碼的「text」段和包含已初始化數據的「data」段。BSS段的變數只有名稱和大小卻沒有值。此名後來被許多文件格式使用,包括PE。「以符號開始的塊」指的是編譯器處理未初始化數據的地方。BSS節不包含任何數據,只是簡單的維護開始和結束的地址,以便內存區能在運行時被有效地清零。BSS節在應用程序的二進制映象文件中並不存在。
在採用段式內存管理的架構中(比如intel的80x86系統),bss段(Block Started by Symbol segment)通常是指用來存放程序中未初始化的全局變數的一塊內存區域,一般在初始化時bss 段部分將會清零。bss段屬於靜態內存分配,即程序一開始就將其清零了。
比如,在C語言之類的程序編譯完成之後,已初始化的全局變數保存在.data 段中,未初始化的全局變數保存在.bss 段中。
text和data段都在可執行文件中(在嵌入式系統里一般是固化在鏡像文件中),由系統從可執行文件中載入;而bss段不在可執行文件中,由系統初始化。
⑺ 如何理解Java虛擬機棧
堆是堆(heap),棧是棧(stack),堆棧是棧。
棧中分配的是基本類型和自定義對象的引用。
堆中分配的是對象,也就是new出來的東西。 被所有線程共享。
方法區/靜態區 存放的是類信息和static變數、常量。 被所有線程共享。
也可以這么理解:堆是用來存放對象的,棧是用來運行程序的。
堆:java的垃圾回收器會自動的回收這些不用的數據。缺點是由於要動態的分配內存,存儲效率會比較的慢。
棧:棧的優勢是存取效率比較快,僅次於寄存器,棧數據可以共享。但缺點是棧中的數據大小和生存期的固定的,缺乏靈活性。
一般每個方法的調用都會獨立有一個棧來保存對象的引用變數,在方法返回後,棧會清空,當在一段代碼塊定義一個變數時,Java就在棧中為這個變數分配內存空間,當超過變數的作用域後,Java會自動釋放掉為該變數所分配的內存空間,該內存空間可以立即被另作他用。
以32位地址操作系統為例,一個進程可擁有的虛擬內存地址范圍為0-2^32。分為兩部分,一部分留給kernel使用(kernel virtual memory),剩下的是進程本身使用, 即圖中的process virtual memory。
一個程序本質上都是由bss段、data段、text段三個組成的
bss段(Block Started by Symbol segment)通常是指用來存放程序中未初始化的全局變數的一塊內存區域,一般在初始化時bss 段部分將會清零。bss段屬於靜態內存分配,即程序一開始就將其清零了。
在C語言之類的程序編譯完成之後,已初始化的全局變數保存在.data 段中,未初始化的全局變數保存在.bss 段中。
text和data段都在可執行文件中(在嵌入式系統里一般是固化在鏡像文件中),由系統從可執行文件中載入;而bss段不在可執行文件中,由系統初始化。
⑻ 關於c語言的數組
你提這個問題涉及幾個方面
1.靜態存儲區
2.靜態數組(static數組),全局數組,動態數組,局部數組
3.給數組賦初值
下面分別解答
1.靜態存儲區/BSS段/棧
一個程序一般分為3段:text段,data段,bss段
text段:就是放程序代碼的,編譯時確定,只讀,
data段:存放在編譯階段(而非運行時)就能確定的數據,可讀可寫
就是通常所說的靜態存儲區,賦了初值的全局變數和靜態變數存放在這個區域,常量也存放在這個區域
bss段:定義而沒有賦初值的全局變數和靜態變數,放在這個區域
2.數組定義
函數外不加static定義的數組為全局數組
用static定義靜態數組(函數內或函數外)
用malloc定義動態數組
函數內不加static關鍵字的數組,為局部數組
3.數組賦初值
對全局數組,定義並賦初值,則在data段,定義未賦初值,在bss段
靜態數組也一樣,無論靜態數組是在函數內還是函數外,定義並賦初值,則在data段,定義未賦初值,在bss段
動態數組,全是從堆上分配的
局部數組,從函數的棧上分配的,顯然存儲在棧上,函數結束就釋放
重點區分最具有迷惑性的以下兩種定義
int func1()
{
char s[200]="hello world!";
}
int func2()
{
static char s[200]="hello world!";
}
func1中,"hello world!"為常量數組,存放在data段
數組s從func1的棧上分配,然後常量數組的值復制到數組s中
func2中,"hello world!"為初值,數組s編譯時就確定在data段,
初值為"hello world!"
⑼ 動態和靜態存儲區中數據的初始化有什麼不同
c語言中需要內存來存放數據。而內存主要分為兩類:靜態存儲區和動態存儲區;
1.靜態存儲區分為:只讀數據(READONLY DATA)區、以讀寫數據(RW DATA)區、未初始化區(BSS)。它們都是在程序編譯連接階段確定的,在程序執行的階段不會改變。
2.動態存儲區分為堆和棧。都是程序執行的過程中動態分配的,大小也隨之動態變化。從內存管理的實現的角度看來,堆使用的鏈表實現的,而棧使用的是線性存儲的方法。
棧:棧是先進後出,實際的操作中,棧內存可以有滿棧和空棧的情況,滿棧的情況下,棧指針當前的位子是已經使用的的棧區域;空棧的情況是,棧指針當前的位子是沒有使用的棧區域,所以兩種情況的出入棧,指針和數據的操作先後順序是不同的。
滿棧時:入棧,是先移動指針,在放入數據;出棧則是先出數據,在移動指針;
空棧時:入棧,是先放入數據,在移動指針。出棧則是先移動指針,在出數據;
C語言必須注意的幾個問題:
1.內存泄露:申請一塊內存,但沒有釋放,程序結束也沒回收,導致其他程序不能使用
2.野指針:指一個內存指針已經被釋放free或者realloc,但指針依然在使用。避免野指針的情況,將內存的指針置為NULL,並在程序使用的時候判斷該內存是否為NULL,如為空,則認為該內存已經釋放,不對內存進行訪問。
3.非法釋放內存:原則上講只有被malloc(),calloc()或realloc()分配並通過返回值返回返回的內存才能被釋放,否則釋放除此以外的內存都是非法的。即使有一個指針是*p是malloc,那麼對p1=p++,這個時候free(p1)也是不合法的,但free(p)確實可以的。同樣釋放函數中的局部變數也是非法的.還有一種情況是,對一個堆內存釋放兩次也是錯誤的用法。因為free()函數是不能釋放未分配的堆內存。在程序使用free釋放內存之後,應該將指針置為NULL,free一個NULL地址是沒有問題的。