『壹』 linux程序設計:堆和棧的區別
一、預備知識—程序的內存分配
一個由C/C++編譯的程序佔用的內存分為以下幾個部分
1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變數的值等。其
操作方式類似於數據結構中的棧。
2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回
收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表,呵呵。
3、全局區(靜態區)(static)—,全局變數和靜態變數的存儲是放在一塊的,初始化的
全局變數和靜態變數在一塊區域, 未初始化的全局變數和未初始化的靜態變數在相鄰的另
一塊區域。 - 程序結束後由系統釋放。
4、文字常量區 —常量字元串就是放在這里的。 程序結束後由系統釋放
5、程序代碼區—存放函數體的二進制代碼。
二、例子程序
這是一個前輩寫的,非常詳細
//main.cpp
int a = 0; 全局初始化區
char *p1; 全局未初始化區
main()
{
int b; 棧
char s[] = "abc"; 棧
char *p2; 棧
char *p3 = "123456"; 123456/0在常量區,p3在棧上。
static int c =0; 全局(靜態)初始化區
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得來得10和20位元組的區域就在堆區。
strcpy(p1, "123456"); 123456/0放在常量區,編譯器可能會將它與p3所指向的"123456"
優化成一個地方。
}
二、堆和棧的理論知識
2.1申請方式
stack:
由系統自動分配。 例如,聲明在函數中一個局部變數 int b; 系統自動在棧中為b開辟空
間
heap:
需要程序員自己申請,並指明大小,在c中malloc函數
如p1 = (char *)malloc(10);
在C++中用new運算符
如p2 = new char[10];
但是注意p1、p2本身是在棧中的。
2.2
申請後系統的響應
棧:只要棧的剩餘空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢
出。
堆:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,
會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閑結點鏈表
中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的
首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。
另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部
分重新放入空閑鏈表中。
2.3申請大小的限制
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意
思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有
的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將
提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲
的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小
受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
2.4申請效率的比較:
棧由系統自動分配,速度較快。但程序員是無法控制的。
堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配內存,他不是在堆,也不是在棧是
直接在進程的地址空間中保留一塊內存,雖然用起來最不方便。但是速度快,也最靈活。
2.5堆和棧中的存儲內容
棧: 在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可
執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧
的,然後是函數中的局部變數。注意靜態變數是不入棧的。
當本次函數調用結束後,局部變數先出棧,然後是參數,最後棧頂指針指向最開始存的地
址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆:一般是在堆的頭部用一個位元組存放堆的大小。堆中的具體內容由程序員安排。
2.6存取效率的比較
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在運行時刻賦值的;
而bbbbbbbbbbb是在編譯時就確定的;
但是,在以後的存取中,在棧上的數組比指針所指向的字元串(例如堆)快。
比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
對應的匯編代碼
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一種在讀取時直接就把字元串中的元素讀到寄存器cl中,而第二種則要先把指針值讀到
edx中,再根據edx讀取字元,顯然慢了。
2.7小結:
堆和棧的區別可以用如下的比喻來看出:
使用棧就象我們去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就 走,不必理會切菜、洗菜等准備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自 由度小。
使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由
『貳』 Linux 怎麼查看一個進程的堆棧
方法一:pstack pid
NAME
pstack - print a stack trace of a running process
SYNOPSIS
pstack pid
DESCRIPTION
pstack attaches to the active process named by the pid on the command line, and prints out an execution stack trace. If ELF symbols exist in the binary (usually the case
unless you have run strip(1)), then symbolic addresses are printed as well.
If the process is part of a thread group, then pstack will print out a stack trace for each of the threads in the group.
SEE ALSO
nm(1), ptrace(2), gdb(1)
方法二:gstack pid
NAME
gstack - print a stack trace of a running process
SYNOPSIS
gstack pid
DESCRIPTION
gstack attaches to the active process named by the pid on the command line, and prints out an execution stack trace. If ELF symbols exist in the binary (usually the case
unless you have run strip(1)), then symbolic addresses are printed as well.
If the process is part of a thread group, then gstack will print out a stack trace for each of the threads in the group.
SEE ALSO
nm(1), ptrace(2), gdb(1)
方胡敬升法三:
使用gdb 然後attach 進程ID,然後再使用命令 thread apply all bt。
方法一和褲老方法二一樣,方法三可以查看更多稿拿的信息。
『叄』 linux系統最大堆棧內存
linux系統最大堆棧消搜內存是-Xmx512m。根據查找相關公開資料顯敏簡示,linux系統堆棧大小拿拿歷的配置啟動參數,初始堆大小-Xms32m最大堆大小-Xmx512m。
『肆』 Linux進程虛擬地址空間的分布,以及堆和棧的區別
一、具體分布如圖所示:
二、關於堆和棧
(1)分配方式:
棧:由編譯器自動分配釋放,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧。
堆: 一般由程序員分配釋放,它的分配方式類似於鏈表。
(2)申請後系統的響應:
棧:只要所申請的空間小於棧的剩餘空間,則系統為程序分配內存,否則棧溢出。
堆:操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,遍歷該鏈表,找出第一個大於所申請空間的節點,然後將其從鏈表中刪除並分配,如果沒用完,則系統會把多餘的重新放回到鏈表中。
(3)申請大小的限制:
棧:棧是高地址向低地址擴展的連續內存,棧的大小一般是2M;
堆:堆是低地址向高地址擴展的不連續內存,堆的大小與計算機有效的虛擬內存有關系。
(4)申請效率:
棧:由系統自動分配,速度較快;
堆:速度慢,容易產生內存碎片;
關於Linux命令的介紹,看看《linux就該這么學》,具體關於這一章地址3w(dot)linuxprobe/chapter-02(dot)html.
『伍』 linux 設置堆棧大小 為無限制
你好。
執行命令ulimit -a,查看棧大小的限制。
通過使用 ulimit -s 數字 進行設置。
『陸』 linux鏌ョ湅鍫嗘爤淇℃伅linux鏌ョ湅鍫嗘爤
lwip鍗忚璇﹁В錛
lwIP鏄涓涓杞婚噺綰х殑TCP/IP鍗忚鏍堬紝瀹冨湪宓屽叆寮忕郴緇熶腑寰楀埌浜嗗箍娉涘簲鐢ㄣ備互涓嬫槸lwIP鍗忚鐨勪竴浜涜﹁В錛
鍗忚鏋舵瀯錛歭wIP鍗忚鏍堜富瑕佺敱鍥涗釜灞傛瀯鎴愶紝鍒嗗埆鏄搴旂敤灞傘佷紶杈撳眰銆佺綉緇滃眰鍜岀綉緇滄帴鍙e眰銆
TCP/IP鍗忚鏀鎸侊細lwIP鍗忚鏍堟敮鎸佸父鐢ㄧ殑TCP/IP鍗忚錛屽俆CP銆乁DP銆両P銆両CMP絳夈
鍐呭瓨綆$悊錛歭wIP鍗忚鏍堜嬌鐢ㄤ簡涓縐嶇О涓簆buf鐨勬暟鎹緇撴瀯鏉ョ$悊鍐呭瓨錛宲buf鏄涓涓鏁版嵁鍖呯紦鍐插尯錛屽彲浠ュ寘鍚涓涓鎴栧氫釜鏁版嵁鍖呫
鎺ュ彛綆$悊錛歭wIP鍗忚鏍堟敮鎸佸氱嶇綉緇滄帴鍙g被鍨嬶紝濡侲thernet銆丳PP銆丼LIP絳夈
鏀鎸佸氱嶆搷浣滅郴緇燂細lwIP鍗忚鏍堝彲浠ュ湪澶氱嶆搷浣滅郴緇熶笂榪愯岋紝濡侺inux銆丗reeRTOS銆乽C/OS絳夈
鏀鎸佸崗璁鎵╁睍錛歭wIP鍗忚鏍堟敮鎸佸崗璁鎵╁睍錛岀敤鎴峰彲浠ユ牴鎹闇瑕佹坊鍔犳柊鐨勫崗璁銆
鎬諱箣錛宭wIP鍗忚鏍堟槸涓嬈懼姛鑳戒赴瀵屻佽交閲忕駭鐨凾CP/IP鍗忚鏍堬紝鐗瑰埆閫傚悎浜庡祵鍏ュ紡緋葷粺涓鐨勭綉緇滃簲鐢ㄣ
shell鏍堝備綍淇鏀癸紵
鍦/etc/profile鐨勬渶鍚庨潰娣誨姞ulimit-sunlimited淇濆瓨錛宻ource/etc/profile浣誇慨鏀規枃浠剁敓鏁坙inux鏌ョ湅淇鏀圭嚎紼嬮粯璁ゆ爤絀洪棿澶у皬錛歶limit-s1銆侀氳繃鍛戒護ulimit-s鏌ョ湅linux鐨勯粯璁ゆ爤絀洪棿澶у皬錛岄粯璁ゆ儏鍐典笅涓10240鍗10M2銆侀氳繃鍛戒護ulimit-s璁劇疆澶у皬鍊間復鏃舵敼鍙樻爤絀洪棿澶у皬錛歶limit-s102400錛屽嵆淇鏀逛負100M3銆佸彲浠ュ湪/etc/rc.local鍐呭姞鍏ulimit-s102400鍒欏彲浠ュ紑鏈哄氨璁劇疆鏍堢┖闂村ぇ灝4銆佸湪/etc/security/limits.conf涓涔熷彲浠ユ敼鍙樻爤絀洪棿澶у皬錛#
linux綰跨▼榛樿ゆ爤澶氬ぇ錛
linux鐨勭嚎紼嬫爤澶у皬鍙浠ヤ嬌鐢╱limit-s鏌ョ湅錛屽逛簬ubuntu2.6鐨勫唴鏍哥嚎紼嬫爤鐨勯粯璁ゅぇ灝忎負8M
『柒』 怎麼解決 LINUX 堆棧溢出內存的問題
【緩沖區溢出的處理】
你屋子裡的門和窗戶越少,入侵者進入的方式就越少……
由於緩沖區溢出是一個編程問題,所以只能通過修復被破壞的程序的代碼而解決問題。州隱如果你沒有源代碼,從上面「堆棧溢出攻擊」的原理可以看出,要防止此類攻擊,我們可以:
① 開放程序時仔細檢查溢出情況,不允許數據溢出緩沖區。由於編程和編程語言的原因,這非常困難,而且不適合大量已經在使用的程序;
② 使用檢查堆棧溢出的編譯器或者在程序中加入某些記號,以便程序運行時確認禁止黑客有意造成的溢出。問題是無法針對已有程序,對新程序來講,需要修改編譯器;
③ 經常檢查你的操作系統和應用程序提供商的站點,一旦發現他們提供的補丁程序,就馬上下載並且應用在系統上,這是最好的方法。但是系統管理員總要比攻擊者慢 一步,如果這個有問題的軟體是可選的,甚團頃至是臨時的,把它從你的系統中刪除。舉另外一個例 子,你屋子裡的門和窗戶越少,入侵者進入的方式就越少。
----------------------------------------------------------------------------------------------------------------------------------------
char buf[3];
memset(buf,0x55,10);
這個程序就存在溢出
對數據塊的訪問超出該數據塊的地址范圍
===================================================================================
【一個檢測工具】
Valgrind 是一款 Linux下(支持 x86、x86_64和ppc32)程序的內存調試工具,它可以對編譯後的二進製程序進行內存使用監測(C語言中的 malloc 和 free,以及 C++ 中的 new 和 delete),找出內存泄漏問題。
Valgrind 中包含的冊或廳 Memcheck 工具可以檢查以下的程序錯誤:
使用未初始化的內存 (Use of uninitialised memory)
使用已經釋放了的內存 (Reading/writing memory after it has been free』d)
使用超過 malloc 分配的內存空間(Reading/writing off the end of malloc』d blocks)
對堆棧的非法訪問(Reading/writing inappropriate areas on the stack)
申請的空間是否有釋放(Memory leaks – where pointers to malloc』d blocks are lost forever)
malloc/free/new/delete 申請和釋放內存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
src 和 dst 的重疊(Overlapping src and dst pointers in memcpy() and related functions)
重復 free
① 編譯安裝 Valgrind:
# wget http://valgrind.org/downloads/valgrind-3.4.1.tar.bz2
# tar xvf valgrind-3.4.1.tar.bz2
# cd valgrind-3.4.1/
# ./configure
…………
Primary build target: X86_LINUX
Secondary build target:
Default supp files: exp-ptrcheck.supp xfree-3.supp xfree-4.supp glibc-2.X-drd.supp glibc-2.34567-NPTL-helgrind.supp glibc-2.5.supp
# make
# make install
# whereis valgrind
valgrind:
/usr/bin/valgrind
/usr/lib/valgrind
/usr/local/bin/valgrind
/usr/local/lib/valgrind
/usr/include/valgrind
/usr/share/man/man1/valgrind.1.gz
運行程序
使用示例:對「ls」程序進程檢查,返回結果中的「definitely lost: 0 bytes in 0 blocks.」表示沒有內存泄漏。
# /usr/local/bin/valgrind --tool=memcheck --leak-check=full ls /
==29801== Memcheck, a memory error detector.
==29801== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==29801== Using LibVEX rev 1884, a library for dynamic binary translation.
==29801== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==29801== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==29801== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==29801== For more details, rerun with: -v
==29801==
bin etc lost+found mnt proc selinux sys usr
boot home media net root smokeping tftpboot var
dev lib misc opt sbin srv tmp
==29801==
==29801== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from 1)
==29801== malloc/free: in use at exit: 14,744 bytes in 32 blocks.
==29801== malloc/free: 162 allocs, 130 frees, 33,758 bytes allocated.
==29801== For counts of detected errors, rerun with: -v
==29801== searching for pointers to 32 not-freed blocks.
==29801== checked 139,012 bytes.
==29801==
==29801== LEAK SUMMARY:
==29801== definitely lost: 0 bytes in 0 blocks.
==29801== possibly lost: 0 bytes in 0 blocks.
==29801== still reachable: 14,744 bytes in 32 blocks.
==29801== suppressed: 0 bytes in 0 blocks.
==29801== Reachable blocks (those to which a pointer was found) are not shown.
==29801== To see them, rerun with: --leak-check=full --show-reachable=yes
----------------------------------------------------------------------------------------------------------------------------------------
# /usr/local/bin/valgrind --tool=memcheck --leak-check=full ps /
==29898== Memcheck, a memory error detector.
==29898== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==29898== Using LibVEX rev 1884, a library for dynamic binary translation.
==29898== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==29898== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==29898== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==29898== For more details, rerun with: -v
==29898==
ERROR: Garbage option.
********* simple selection ********* ********* selection by list *********
-A all processes -C by command name
-N negate selection -G by real group ID (supports names)
-a all w/ tty except session leaders -U by real user ID (supports names)
-d all except session leaders -g by session OR by effective group name
-e all processes -p by process ID
T all processes on this terminal -s processes in the sessions given
a all w/ tty, including other users -t by tty
g OBSOLETE -- DO NOT USE -u by effective user ID (supports names)
r only running processes U processes for specified users
x processes w/o controlling ttys t by tty
*********** output format ********** *********** long options ***********
-o,o user-defined -f full --Group --User --pid --cols --ppid
-j,j job control s signal --group --user --sid --rows --info
-O,O preloaded -o v virtual memory --cumulative --format --deselect
-l,l long u user-oriented --sort --tty --forest --version
-F extra full X registers --heading --no-heading --context
********* misc options *********
-V,V show version L list format codes f ASCII art forest
-m,m,-L,-T,H threads S children in sum -y change -l format
-M,Z security data c true command name -c scheling class
-w,w wide output n numeric WCHAN,UID -H process hierarchy
==29898==
==29898== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 14 from 1)
==29898== malloc/free: in use at exit: 16 bytes in 2 blocks.
==29898== malloc/free: 20 allocs, 18 frees, 2,344 bytes allocated.
==29898== For counts of detected errors, rerun with: -v
==29898== searching for pointers to 2 not-freed blocks.
==29898== checked 263,972 bytes.
==29898==
==29898== 8 bytes in 1 blocks are definitely lost in loss record 2 of 2
==29898== at 0x4005A88: malloc (vg_replace_malloc.c:207)
==29898== by 0xBFF6DF: strp (in /lib/libc-2.5.so)
==29898== by 0x804A464: (within /bin/ps)
==29898== by 0x804A802: (within /bin/ps)
==29898== by 0x804964D: (within /bin/ps)
==29898== by 0xBA5E8B: (below main) (in /lib/libc-2.5.so)
==29898==
==29898== LEAK SUMMARY:
==29898== definitely lost: 8 bytes in 1 blocks.
==29898== possibly lost: 0 bytes in 0 blocks.
==29898== still reachable: 8 bytes in 1 blocks.
==29898== suppressed: 0 bytes in 0 blocks.
==29898== Reachable blocks (those to which a pointer was found) are not shown.
==29898== To see them, rerun with: --leak-check=full --show-reachable=yes