国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

C語言的那些小秘密之函數的調用關系

發布時間:2016-2-18 14:10    發布者:designapp
關鍵詞: C語言 , 函數
  顯示函數的調用關系是調試器的必備功能,如果我們在程序的運行中出現了崩潰的情況,通過函數的調用關系可以快速定位問題的根源,懂得函數調用關系的實現原理也可以擴充自己的知識面,在沒有調試器的情況下,我們也可以自己來實現顯示函數的調用關系。在我們自己動手寫backtrace函數之前,先來看看glibc提供的backtrace函數的使用。代碼如下:
  #include
  #include
  #include
  #define MAX_LEVEL 4
  static void call2()
  {
  int i = 0;
  void* buffer[MAX_LEVEL] = {0};
  int size=backtrace(buffer, MAX_LEVEL);
  for(i = 0; i t.sh;. t.sh;rm -f t.sh
  輸出結果為:
  /home/shiyan/sss.c:12
  /home/shiyan/sss.c:27
  /home/shiyan/sss.c:34
  /home/shiyan/sss.c:40
  接下來看看在棧中數據的結構。
  

                                
                  函數參數的壓棧是從右向左的,即先壓最后一個參數,在壓倒數第二個,以此類推,最后才壓入第一個參數。為了加深大家的印象,下面我給出一個測試代碼:
  #include
  void turn(int x, int y, int z)
  {
  printf("x = %d at [%X]\n", x, &x);
  printf("y = %d at [%X]\n", y, &y);
  printf("z = %d at [%X]\n", z, &z);
  }
  int main(int argc, char *argv[])
  {
  turn(1, 2, 3);
  return 0;
  }
  運行結果為:
  


  比較打印出來的地址可以看出參數z的地址是最大的,x的地址最小。
  參數的壓棧工作完成之后,接下來就依次是EIP、EBP、臨時變量的壓棧操作了。最后壓入的是被調用函數本身,并為它分配臨時的變量空間,而對于不同版本的gcc的處理方式各有不同,老版本的gcc第一個臨時變量放在最高的地址,第二個其次,依次順序分布,新版本的gcc則與之相反。
  實現backtrace()函數的調用關系,其步驟如下:
  1.獲取當前函數的EBP;
  2.通過EBP獲得調用者得EIP;
  3.通過EBP獲得上一級的EBP;
  4.重復這個過程,知道結束。
  自己實現的backtrace()函數,代碼如下:
  #include
  #define MAX_LEVEL 4
  #define OFFSET 4
  int backtrace(void** buffer, int size)
  {
  int n = 0x23f;
  int* p = &n;
  int i = 0;
  int ebp = p[1 + OFFSET];
  int eip = p[2 + OFFSET];
  for(i = 0; i t.sh;. t.sh;rm -f t.sh
  root@ubuntu:/home/shiyan# ./tt |awk '{print "addr2line "$3" -e tt"}'>t.sh;. t.sh;rm -f t.sh
  /home/shiyan/bac.c:32
  /home/shiyan/bac.c:47
  /home/shiyan/bac.c:54
  /home/shiyan/bac.c:60
  在此重點介紹下backtrace()函數的實現原理。
  通過 int* p = &n;來獲取第一個臨時變量的位置,因為我使用的是新版本的gcc,有5個臨時變量,所以EIP的值存放在p[6]中,EBP的的值存放在p[5],通過 buffer[i ] = (void*)eip;可以把eip的強制轉換為可以指向任意類型的指針, 接下來通過 p = (int*)ebp;來獲得上一個函數的ebp,獲得ebp之后由ebp和eip的位置關系可以得到eip,由于ebp指向的單元存儲的是上一個函數的ebp,所以用一個簡單的for循環就能實現了。
  另外在頭文件"execinfo.h"中除了聲明backtrace()函數外,還有如下兩個函數也用于獲取當前線程的函數調用堆棧。
  char ** backtrace_symbols (void *const *buffer, int size)
  backtrace_symbols將從backtrace函數獲取的信息轉化為一個字符串數組. 參數buffer應該是從backtrace函數獲取的數組指針,size是該數組中的元素個數(backtrace的返回值)
  函數返回值是一個指向字符串數組的指針,它的大小同buffer相同.每個字符串包含了一個相對于buffer中對應元素的可打印信息.它包括函數名,函數的偏移地址,和實際的返回地址
  現在,只有使用ELF二進制格式的程序和苦衷才能獲取函數名稱和偏移地址.在其他系統,只有16進制的返回地址能被獲取.另外,你可能需要傳遞相應的標志給鏈接器,以能支持函數名功能(比如,在使用GNU ld的系統中,你需要傳遞(-rdynamic)),該函數的返回值是通過malloc函數申請的空間,因此調用這必須使用free函數來釋放指針。
  注意:如果不能為字符串獲取足夠的空間函數的返回值將會為NULL。
  Function:void backtrace_symbols_fd (void *const *buffer, int size, int fd)
  backtrace_symbols_fd與backtrace_symbols 函數具有相同的功能,不同的是它不會給調用者返回字符串數組,而是將結果寫入文件描述符為fd的文件中,每個函數對應一行.它不需要調用malloc函數,因此適用于有可能調用該函數會失敗的情況。
  還是那句話,以上內容難免有誤,如有錯誤,請糾正。
本文地址:http://m.qingdxww.cn/thread-160850-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • Chiptorials ——使用ATECC608 TrustFLEX實現基本非對稱身份驗證
  • FPGA設計流程培訓教程
  • Chiptorials——如何使用ATECC608 TrustFLEX實現公鑰輪換
  • 無線充電基礎知識及應用培訓教程
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 97免费在线视频 | 草逼免费| 欧洲亚洲一区 | 网站大全黄免费 | 日韩高清在线日韩大片观看网址 | 久久久这里只有精品加勒比 | 国产99久久久国产精品小说 | 国内自产一区c区 | 日韩欧美一区二区三区免费观看 | 久久99热这里只有精品免费看 | 国产美女毛片 | 在线播放亚洲精品 | 色吧五月婷婷 | 韩国视频一区二区 | 91免费版在线观看 | 欧美日韩视频在线成人 | 成人午夜一区二区三区视频 | 日韩欧美一区二区中文字幕 | 日本一区欧美 | 被cao的奶水直喷 | 四虎国产精品永久在线看 | 男性天堂| 99久久精品免费看国产情侣 | 亚洲精品在线播放视频 | 4虎在线观看 | 日本岛国大片 | 日韩在线免费视频 | 日本精品久久久一区二区三区 | 热最近热久点 | 最新国产三级在线观看不卡 | 97人人在线观看 | 青青青国产在线观看 | 成年黄色网址 | 九色自拍视频 | 99久视频 | 在线观看亚洲视频 | 在线观看精品视频一区二区三区 | 日韩中文字幕在线播放 | 黄网站视频观看免费 | 机机对机机在线观看 | 天天操中文字幕 |