色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > C語言中入棧順序與變量輸出

C語言中入棧順序與變量輸出 時間:2018-09-29      來源:未知

1).內存區域劃分:

圖1 程序運行時的內存區域

如圖所示:C程序中,棧區主要存儲函數的參數,局部變量等,并且棧底為高地址,棧頂為低地址(如圖:由高地址向低地址擴展)。

2).入棧順序:

A:函數參數的入棧順序:自右向左

原因:

函數參數的入棧順序和具體編譯器的實現有關。有些參數是從左向右入棧,如:Pascal語言從左到右入棧(不支持變參),被調用者清棧;有些語言還可以通過修飾符進行指定,如:Visual C++;但是C語言(cdecl)采用自右向左的方式入棧,調用者清棧。

這是因為自右向左入棧順序的好處就是可以動態的變化參數個數。通過堆棧分析可知,自左向右入棧方式中,前面的參數會被壓入棧底。除非知道參數個數,否則無法通過棧指針的相對位移求得左邊的參數。這樣就無法實現可變參數。因此,C語言采用自右向左入棧順序,主要是因為實現可變長參數形式(如:printf函數)。可變長參數主要通過第一個定參數來確定參數列表,所以自右向左入棧后,函數調用時棧頂指針指向的就是參數列表的第一個確定參數,這樣就可以了。

例子1:

#include <stdio.h>

void print(int x, int y, int z)

{

printf("x = %d addr %p\n", x, &x);

printf("y = %d addr %p\n", y, &y);

printf("z = %d addr %p\n", z, &z);

}

 

int main()

{

print(1,2,3);//自右向入壓棧

return 0;

}

 

運行結果:

x = 1 addr 0xbfb5c760 //棧頂,后壓棧

y = 2 addr 0xbfb5c764

z = 3 addr 0xbfb5c768 //棧底,先入棧

B:局部變量的入棧順序:

在沒有棧溢出保護機制下編譯時,所有局部變量按系統為局部變量申請內存中棧空間的順序,即:先申請哪個變量,哪個先入棧,正向的。也就是說,編譯器給變量空間的申請是直接按照變量申請順序執行的。(見例子2)

在有棧溢出保護機制下編譯時,入棧順序有所改變,先按照類型劃分,再按照定義變量的先后順序劃分,即:char型先申請,int類型后申請(與編譯器溢出保護時的規定相關);然后棧空間的申請順序與代碼中變量定義順序相反(后定義的先入棧)。(見例子2)

例子2:stack.c

#include <stdio.h>

 

int main()

{

int a[5] = {1,2,3,4,5};

int b[5] = {6,7,8,9,10};

char buf1[6] = "abcde";

char buf2[6] = "fghij";

int m = -1;

int n = -2;

printf("a[0]  = %3d, addr: %p\n", a[0], &a[0]);

printf("a[4]  = %3d, addr: %p\n", a[4], &a[4]);

printf("b[0]  = %3d, addr: %p\n", b[0], &b[0]);

printf("b[4]  = %3d, addr: %p\n", b[4], &b[4]);

printf("buf1[0] = %3d, addr: %p\n", buf1[0], &buf1[0]);

printf("buf1[5] = %3d, addr: %p\n", buf1[5], &buf1[5]);

printf("buf2[0] = %3d, addr: %p\n", buf2[0], &buf2[0]);

printf("buf2[5] = %3d, addr: %p\n", buf2[5], &buf2[5]);

printf("m  = %3d, addr: %p\n", m, &m);

printf("n  = %3d, addr: %p\n", n, &n);

}

沒有棧溢出保護機制下的編譯:

$ gcc stack.c -g -o stack -fno-stack-pprotector

$ ./stack

a[0]  =   1, addr: 0xbfa5185c //數組內部,地址由低到高不變

a[4]  =   5, addr: 0xbfa5186c //棧底,高地址

b[0]  =   6, addr: 0xbfa51848

b[4]  =  10, addr: 0xbfa51858

buf1[0] =  97, addr: 0xbfa51842

buf1[5] =   0, addr: 0xbfa51847

buf2[0] = 102, addr: 0xbfa5183c

buf2[5] =   0, addr: 0xbfa51841

=  -1, addr: 0xbfa51838

=  -2, addr: 0xbfa51834  //棧頂,低地址

可以看出入棧順序:a -> b -> buf1 -> buf2 -> m -> n(先定義,先壓棧)

 

棧溢出保護機制下的編譯:

$ gcc stack.c -g -o stack

$ ./stack

a[0]  =   1, addr: 0xbfc69130 //棧頂

a[4]  =   5, addr: 0xbfc69140

b[0]  =   6, addr: 0xbfc69144

b[4]  =  10, addr: 0xbfc69154 

buf1[0] =  97, addr: 0xbfc69160 //char類型,優先入棧

buf1[5] =   0, addr: 0xbfc69165

buf2[0] = 102, addr: 0xbfc69166

buf2[5] =   0, addr: 0xbfc6916b //棧底

=  -1, addr: 0xbfc69158

=  -2, addr: 0xbfc6915c //int類型,后壓棧

 

可以看出入棧順序:buf2 -> buf1 -> n -> m -> b -> a(char類型先入棧,int類型后入棧;先定義,后壓棧)

3).指針越界輸出:

例子3:stack1.c

#include <stdio.h>

 

int main()

{

char buf1[6] = "abcef";

char buf2[6] = "fghij";

int a[5] = {1,2,3,4,5};

int b[5] = {6,7,8,9,10};

int m = -1;

int n = -2;

char *p = &buf2[0];

printf("a[0]  = %3d, addr: %p\n", a[0], &a[0]);

printf("a[4]  = %3d, addr: %p\n", a[4], &a[4]);

printf("b[0]  = %3d, addr: %p\n", b[0], &b[0]);

printf("b[4]  = %3d, addr: %p\n", b[4], &b[4]);

printf("buf1[0] = %3d, addr: %p\n", buf1[0], &buf1[0]);

printf("buf1[5] = %3d, addr: %p\n", buf1[5], &buf1[5]);

printf("buf2[0] = %3d, addr: %p\n", buf2[0], &buf2[0]);

printf("buf2[5] = %3d, addr: %p\n", buf2[5], &buf2[5]);

printf("m  = %3d, addr: %p\n", m, &m);

printf("n = %3d, addr: %p\n", n, &n);

printf("p[0]  = %3d, addr: %p\n", p[0], &p[0]);

printf("p[6]  = %3d, addr: %p\n", p[6], &p[6]);

printf("p[-6]  = %3d, addr: %p\n", p[-6], &p[-6]);

printf("p[-42]  = %3d, addr: %p\n", p[-42], &p[-42]);

printf("p[-43]  = %3d, addr: %p\n", p[-43], &p[-43]);

printf("p[-53]  = %3d, addr: %p\n", p[-53], &p[-53]);

printf("p[-54]  = %3d, addr: %p\n", p[-54], &p[-54]);

printf("p[-55]  = %3d, addr: %p\n", p[-55], &p[-55]);

printf("p[-56]  = %3d, addr: %p\n", p[-56], &p[-56]);

printf("p[-57]  = %3d, addr: %p\n", p[-57], &p[-57]);

printf("p[-58]  = %3d, addr: %p\n", p[-58], &p[-58]);

printf("p[-59]  = %3d, addr: %p\n", p[-59], &p[-59]);

}

棧溢出保護機制下的編譯:

$ gcc stack1.c -g -o stack1

$ ./stack1

a[0]  =   1, addr: 0xbff5ab6c //棧頂,0xbff5ab6c,低地址

a[4]  =   5, addr: 0xbff5ab7c

b[0]  =   6, addr: 0xbff5ab80

b[4]  =  10, addr: 0xbff5ab90

buf1[0] =  97, addr: 0xbff5aba0 //&p[-6]

buf1[5] =   0, addr: 0xbff5aba5

buf2[0] = 102, addr: 0xbff5aba6 //&p[0]

buf2[5] =   0, addr: 0xbff5abab //棧底,0xbff5abab,高地址--->&p[6]:越界,值隨機

=  -1, addr: 0xbff5ab94

=  -2, addr: 0xbff5ab98

p[0]  = 102, addr: 0xbff5aba6 //&buf2[0]

p[6]  =   0, addr: 0xbff5abac //&buf2[6],越界,無初始值,值隨機

p[-6]  =  97, addr: 0xbff5aba0 //&buf1[0],越界,已有初始值,buf1[0],p[-6]為97

p[-42]  =   5, addr: 0xbff5ab7c //&a[4]

p[-43]  =   0, addr: 0xbff5ab7b //&a[4] - 1字節,大小0x00 = 0

p[-53]  =   0, addr: 0xbff5ab71 //&a[1] + 1字節,大小0x00 = 0

p[-54]  =   2, addr: 0xbff5ab70 //&a[1]

p[-55]  =   0, addr: 0xbff5ab6f //p[-55]到p[-58]能看出Linux是小端存儲。

p[-56]  =   0, addr: 0xbff5ab6e //小端存儲:低地址存低位,高地址存高位

p[-57]  =   0, addr: 0xbff5ab6d //a[0]=1,即:0x01 0x00 0x00 0x00(低位到高位)

p[-58]  =   1, addr: 0xbff5ab6c //&a[0]

p[-59]  =   -65, addr: 0xbff5ab6b //&a[0] - 1字節,越界,無初始值,值隨機

入棧順序:(棧底:高地址)buf2 -> buf1 -> n -> m -> b -> a[4] -> a[0](棧頂:低地址)

&p[6]--&p[0]--&p[-6]--------------&p[-42]--&p[-58]--&p[-59]

問題:指針p越界會出現問題,如果在p[-6] = 'k';那么會導致因越界覆蓋內存里面buf1[0]的值。

上一篇:ZigBee的組網流程圖

下一篇:Linux下Samba服務器的安裝與配置(簡單實用)

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5京公海網安備11010802025203號

回到頂部

色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 欧美精品久久一区二区 | 98精品国产高清在线xxxx天堂| 欧美国产激情18| 国产日韩换脸av一区在线观看| 亚洲性视频网站| 97精品国产97久久久久久春色| 亚洲精品免费网站| 欧美成人激情图片网| 国产精品麻豆va在线播放| 在线成人中文字幕| 欧美亚洲国产日韩2020| 亚洲天堂日韩电影| 国内精品小视频在线观看| 日韩激情在线视频| 性欧美xxxx| 国产一区二区三区日韩欧美| 久久久久久一区二区三区| 亚洲精品久久7777777| 久久久久中文字幕2018| 亚洲欧美精品一区二区| 情事1991在线| 日韩一区二区三区在线播放| 国产精品视频网址| 欧美丝袜一区二区| 日韩电影在线观看中文字幕 | 北条麻妃99精品青青久久| 国产成人91久久精品| 久久久久北条麻妃免费看| 国产在线播放不卡| 久久久午夜视频| 在线视频日本亚洲性| 91精品久久久久久| 97不卡在线视频| 久久久精品美女| 日韩精品免费综合视频在线播放| 欧美亚洲另类在线| 欧美精品亚州精品| 亚洲欧美综合v| 国产欧美日韩最新| 欧美亚洲在线播放| 欧美日韩国产精品专区|