linux下core dump


1、前言

  一直在從事linux下后台開發,經常與core文件打交道。還記得剛開始從事linux下開發時,程序突然崩潰了,也沒有任何日志。我不知所措,同事叫我看看core,我卻問什么是core,怎么看。同事鄙視的眼神,我依然在目。后來學會了從core文件中分析原因,通過gdb看出程序掛再哪里,分析前后的變量,找出問題的原因。當時就覺得很神奇,core文件是怎么產生的呢?難道系統會自動產生,可是我在自己的linux系統上面寫個非法程序測試,並沒有產生core問題?這又是怎么回事呢?今天在ngnix的源碼時候,發現可以在程序中設置core dump,又是怎么回事呢?在公司發現生成的core文件都帶有進程名稱、進程ID、和時間,這又是怎么做到的呢?今天帶着這些疑問來說說core文件是如何生成,如何配置。

2、基本概念

   當程序運行的過程中異常終止或崩潰,操作系統會將程序當時的內存狀態記錄下來,保存在一個文件中,這種行為就叫做Core Dump(中文有的翻譯成“核心轉儲”)。我們可以認為 core dump 是“內存快照”,但實際上,除了內存信息之外,還有些關鍵的程序運行狀態也會同時 dump 下來,例如寄存器信息(包括程序指針、棧指針等)、內存管理信息、其他處理器和操作系統狀態和信息。core dump 對於編程人員診斷和調試程序是非常有幫助的,因為對於有些程序錯誤是很難重現的,例如指針異常,而 core dump 文件可以再現程序出錯時的情景。

3、開啟core dump

  可以使用命令ulimit開啟,也可以在程序中通過setrlimit系統調用開啟。

程序中開啟core dump,通過如下API可以查看和設置RLIMIT_CORE

#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim);

參考程序如下所示:

復制代碼
#include <unistd.h>
#include <sys/time.h> #include <sys/resource.h> #include <stdio.h> #define CORE_SIZE 1024 * 1024 * 500 int main() { struct rlimit rlmt; if (getrlimit(RLIMIT_CORE, &rlmt) == -1) { return -1; } printf("Before set rlimit CORE dump current is:%d, max is:%d\n", (int)rlmt.rlim_cur, (int)rlmt.rlim_max); rlmt.rlim_cur = (rlim_t)CORE_SIZE; rlmt.rlim_max = (rlim_t)CORE_SIZE; if (setrlimit(RLIMIT_CORE, &rlmt) == -1) { return -1; } if (getrlimit(RLIMIT_CORE, &rlmt) == -1) { return -1; } printf("After set rlimit CORE dump current is:%d, max is:%d\n", (int)rlmt.rlim_cur, (int)rlmt.rlim_max); /*測試非法內存,產生core文件*/ int *ptr = NULL; *ptr = 10; return 0; }
復制代碼

執行./main, 生成的core文件如下所示

GDB調試core文件,查看程序掛在位置。當core dump 之后,使用命令 gdb program core 來查看 core 文件,其中 program 為可執行程序名,core 為生成的 core 文件名。

4、參考資料

http://www.cnblogs.com/hazir/p/linxu_core_dump.html

http://www.cnblogs.com/niocai/archive/2012/04/01/2428128.html

http://baidutech.blog.51cto.com/4114344/904419/

 

 

 

Linux Core Dump

當程序運行的過程中異常終止或崩潰,操作系統會將程序當時的內存狀態記錄下來,保存在一個文件中,這種行為就叫做Core Dump(中文有的翻譯成“核心轉儲”)。我們可以認為 core dump 是“內存快照”,但實際上,除了內存信息之外,還有些關鍵的程序運行狀態也會同時 dump 下來,例如寄存器信息(包括程序指針、棧指針等)、內存管理信息、其他處理器和操作系統狀態和信息。core dump 對於編程人員診斷和調試程序是非常有幫助的,因為對於有些程序錯誤是很難重現的,例如指針異常,而 core dump 文件可以再現程序出錯時的情景。

Core Dump 名詞解釋

在半導體作為電腦內存材料之前,電腦內存使用的是 磁芯內存(Magnetic Core Memory),Core Dump 中的 Core 沿用了磁芯內存的 Core 表達。圖為磁芯內存的一個單元,來自 Wikipedia.

在 APUE 一書中作者有句話這樣寫的:

Because the file is named core, it shows how long this feature has been part of the Unix System.

這里的 core 就是沿用的是早期電腦磁芯內存中的表達,也能看出 Unix 系統 Core Dump 機制的悠久歷史。

Dump 指的是拷貝一種存儲介質中的部分內容到另一個存儲介質,或者將內容打印、顯示或者其它輸出設備。dump 出來的內容是格式化的,可以使用一些工具來解析它。

現代操作系統中,用 Core Dump 表示當程序異常終止或崩潰時,將進程此時的內存中的內容拷貝到磁盤文件中存儲,以方便編程人員調試。

Core Dump 如何產生

上面說當程序運行過程中異常終止崩潰時會發生 core dump,但還沒說到什么具體的情景程序會發生異常終止或崩潰,例如我們使用 kill -9 命令殺死一個進程會發生 core dump 嗎?實驗證明是不能的,那么什么情況會產生呢?

Linux 中信號是一種異步事件處理的機制,每種信號對應有其默認的操作,你可以在 這里 查看 Linux 系統提供的信號以及默認處理。默認操作主要包括忽略該信號(Ingore)、暫停進程(Stop)、終止進程(Terminate)、終止並發生core dump(core)等。如果我們信號均是采用默認操作,那么,以下列出幾種信號,它們在發生時會產生 core dump:

Signal Action Comment
SIGQUIT Core Quit from keyboard
SIGILL Core Illegal Instruction
SIGABRT Core Abort signal from abort
SIGSEGV Core Invalid memory reference
SIGTRAP Core Trace/breakpoint trap

當然不僅限於上面的幾種信號。這就是為什么我們使用 Ctrl+z 來掛起一個進程或者 Ctrl+C 結束一個進程均不會產生 core dump,因為前者會向進程發出 SIGTSTP 信號,該信號的默認操作為暫停進程(Stop Process);后者會向進程發出SIGINT 信號,該信號默認操作為終止進程(Terminate Process)。同樣上面提到的 kill -9 命令會發出 SIGKILL 命令,該命令默認為終止進程。而如果我們使用 Ctrl+\ 來終止一個進程,會向進程發出 SIGQUIT 信號,默認是會產生 core dump 的。還有其它情景會產生 core dump, 如:程序調用 abort() 函數、訪存錯誤、非法指令等等。

下面舉兩個例子來說明:

  • 終端下比較 Ctrl+C 和 Ctrl+\

    guohailin@guohailin:~$ sleep 10        #使用sleep命令休眠 10 s ^C #使用 Ctrl+C 終止該程序,不會產生 core dump guohailin@guohailin:~$ sleep 10 ^\Quit (core dumped) #使用 Ctrl+\ 退出程序, 會產生 core dump guohailin@guohailin:~$ ls #多出下面一個 core 文件 -rw-------  1 guohailin guohailin 335872 10月 22 11:31 sleep.core.21990 
  • 小程序產生 core dump

    #include <stdio.h>
    
    int main() { int *null_ptr = NULL; *null_ptr = 10; //對空指針指向的內存區域寫,會發生段錯誤 return 0; } 
    #編譯執行
    guohailin@guohailin:~$ ./a.out Segmentation fault (core dumped) guohailin@guohailin:~$ ls #多出下面一個 core 文件 -rw------- 1 guohailin guohailin 200704 10月 22 11:35 a.out.core.22070 

Linux 下打開 Core Dump

我使用的 Linux 發行版是 Ubuntu 13.04,設置生成 core dump 文件的方法如下:

  • 打開 core dump 功能

    • 在終端中輸入命令 ulimit -c ,輸出的結果為 0,說明默認是關閉 core dump 的,即當程序異常終止時,也不會生成 core dump 文件。
    • 我們可以使用命令 ulimit -c unlimited 來開啟 core dump 功能,並且不限制 core dump 文件的大小; 如果需要限制文件的大小,將 unlimited 改成你想生成 core 文件最大的大小,注意單位為 blocks(KB)。
    • 用上面命令只會對當前的終端環境有效,如果想需要永久生效,可以修改文件 /etc/security/limits.conf文件,關於此文件的設置參看 這里 。增加一行:
    # /etc/security/limits.conf
    # #Each line describes a limit for a user in the form: # #<domain> <type> <item> <value> * soft core unlimited 
  • 修改 core 文件保存的路徑

    • 默認生成的 core 文件保存在可執行文件所在的目錄下,文件名就為 core
    • 通過修改 /proc/sys/kernel/core_uses_pid 文件可以讓生成 core 文件名是否自動加上 pid 號。
      例如 echo 1 > /proc/sys/kernel/core_uses_pid ,生成的 core 文件名將會變成 core.pid,其中 pid 表示該進程的 PID。
    • 還可以通過修改 /proc/sys/kernel/core_pattern 來控制生成 core 文件保存的位置以及文件名格式。
      例如可以用 echo "/tmp/corefile-%e-%p-%t" > /proc/sys/kernel/core_pattern 設置生成的 core 文件保存在 “/tmp/corefile” 目錄下,文件名格式為 “core-命令名-pid-時間戳”。這里 有更多詳細的說明!

使用 gdb 調試 Core 文件

產生了 core 文件,我們該如何使用該 Core 文件進行調試呢?Linux 中可以使用 GDB 來調試 core 文件,步驟如下:

  • 首先,使用 gcc 編譯源文件,加上 -g 以增加調試信息;
  • 按照上面打開 core dump 以使程序異常終止時能生成 core 文件;
  • 運行程序,當core dump 之后,使用命令 gdb program core 來查看 core 文件,其中 program 為可執行程序名,core 為生成的 core 文件名。

下面用一個簡單的例子來說明:

#include <stdio.h>
int func(int *p) { int y = *p; return y; } int main() { int *p = NULL; return func(p); } 

編譯加上調試信息, 運行之后core dump, 使用 gdb 查看 core 文件.

guohailin@guohailin:~$ gcc core_demo.c -o core_demo -g
guohailin@guohailin:~$ ./core_demo Segmentation fault (core dumped) guohailin@guohailin:~$ gdb core_demo core_demo.core.24816 ... Core was generated by './core_demo'. Program terminated with signal 11, Segmentation fault. #0 0x080483cd in func (p=0x0) at core_demo.c:5 5 int y = *p; (gdb) where #0 0x080483cd in func (p=0x0) at core_demo.c:5 #1 0x080483ef in main () at core_demo.c:12 (gdb) info frame Stack level 0, frame at 0xffd590a4: eip = 0x80483cd in func (core_demo.c:5); saved eip 0x80483ef called by frame at 0xffd590c0 source language c. Arglist at 0xffd5909c, args: p=0x0 Locals at 0xffd5909c, Previous frame's sp is 0xffd590a4 Saved registers: ebp at 0xffd5909c, eip at 0xffd590a0 (gdb) 

從上面可以看出,我們可以還原 core_demo 執行時的場景,並使用 where 可以查看當前程序調用函數棧幀, 還可以使用 gdb 中的命令查看寄存器,變量等信息.

參考資料

 

 

 

Linux系統調用--getrlimit()與setrlimit()函數詳解

功能描述:
獲取或設定資源使用限制。每種資源都有相關的軟硬限制,軟限制是內核強加給相應資源的限制值,硬限制是軟限制的最大值。非授權調用進程只可以將其軟限制指定為0~硬限制范圍中的某個值,同時能不可逆轉地降低其硬限制。授權進程可以任意改變其軟硬限制。RLIM_INFINITY的值表示不對資源限制。


用法:

#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);

參數:

resource:可能的選擇有

RLIMIT_AS //進程的最大虛內存空間,字節為單位。
RLIMIT_CORE //內核轉存文件的最大長度。
RLIMIT_CPU //最大允許的CPU使用時間,秒為單位。當進程達到軟限制,內核將給其發送SIGXCPU信號,這一信號的默認行為是終止進程的執行。然而,可以捕捉信號,處理句柄可將控制返回給主程序。如果進程繼續耗費CPU時間,核心會以每秒一次的頻率給其發送SIGXCPU信號,直到達到硬限制,那時將給進程發送 SIGKILL信號終止其執行。
RLIMIT_DATA //進程數據段的最大值。
RLIMIT_FSIZE //進程可建立的文件的最大長度。如果進程試圖超出這一限制時,核心會給其發送SIGXFSZ信號,默認情況下將終止進程的執行。
RLIMIT_LOCKS //進程可建立的鎖和租賃的最大值。
RLIMIT_MEMLOCK //進程可鎖定在內存中的最大數據量,字節為單位。
RLIMIT_MSGQUEUE //進程可為POSIX消息隊列分配的最大字節數。
RLIMIT_NICE //進程可通過setpriority() 或 nice()調用設置的最大完美值。
RLIMIT_NOFILE //指定比進程可打開的最大文件描述詞大一的值,超出此值,將會產生EMFILE錯誤。
RLIMIT_NPROC //用戶可擁有的最大進程數。
RLIMIT_RTPRIO //進程可通過sched_setscheduler 和 sched_setparam設置的最大實時優先級。
RLIMIT_SIGPENDING //用戶可擁有的最大掛起信號數。
RLIMIT_STACK //最大的進程堆棧,以字節為單位。

rlim:描述資源軟硬限制的結構體,原型如下

struct rlimit {
  rlim_t rlim_cur;
  rlim_t rlim_max;
};

返回說明:

成功執行時,返回0。失敗返回-1,errno被設為以下的某個值
EFAULT:rlim指針指向的空間不可訪問
EINVAL:參數無效
EPERM:增加資源限制值時,權能不允許

 

延伸閱讀:

ulimit和setrlimit輕松修改task進程資源上限值

在linux系統中,Resouce limit指在一個進程的執行過程中,它所能得到的資源的限制,比如進程的core file的最大值,虛擬內存的最大值等。

Resouce limit的大小可以直接影響進程的執行狀況。其有兩個最重要的概念:soft limit 和 hard limit。

struct rlimit {
  rlim_t rlim_cur;  //soft limit
  rlim_t rlim_max;  //hard limit
};

soft limit是指內核所能支持的資源上限。比如對於RLIMIT_NOFILE(一個進程能打開的最大文件數,內核默認是1024),soft limit最大也只能達到1024。對於RLIMIT_CORE(core文件的大小,內核不做限制),soft limit最大能是unlimited。
hard limit在資源中只是作為soft limit的上限。當你設置hard limit后,你以后設置的soft limit只能小於hard limit。要說明的是,hard limit只針對非特權進程,也就是進程的有效用戶ID(effective user ID)不是0的進程。具有特權級別的進程(具有屬性CAP_SYS_RESOURCE),soft limit則只有內核上限。


我們可以來看一下下面兩條命令的輸出。

復制代碼
sishen@sishen:~$ ulimit -c -n -s
core file size (blocks, -c) 0
open files (-n) 1024
stack size (kbytes, -s) 8192

sishen@sishen:~$ ulimit -c -n -s -H
core file size (blocks, -c) unlimited
open files (-n) 1024
stack size (kbytes, -s) unlimited
復制代碼

-H表示顯示的是hard limit。從結果上可以看出soft limit和hard limit的區別。unlimited表示no limit, 即內核的最大值。


對於resouce limit的讀取修改,有兩種方法。

* 使用shell內建命令ulimit
* 使用getrlimit和setrlimit API

ulimit是改變shell的resouce limit,並達到改變shell啟動的進程的resouce limit效果(子進程繼承)。

usage:ulimit [-SHacdefilmnpqrstuvx [limit]]

當不指定limit的時候,該命令顯示當前值。這里要注意的是,當你要修改limit的時候,如果不指定-S或者-H,默認是同時設置soft limit和hard limit。也就是之后設置時只能減不能增。所以,建議使用ulimit設置limit參數是加上-S。


getrlimit和setrlimit的使用也很簡單,manpage里有很清楚的描述。

int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);

需要注意的是你在setrlimit,需要檢查是否成功來判斷新值有沒有超過hard limit。如下例Linux系統中在應用程序運行過程中經常會遇到程序突然崩潰,提示:Segmentation fault,這是因為應用程序收到了SIGSEGV信號。這個信號提示當進程發生了無效的存儲訪問,當接收到這個信號時,缺省動作是:終止w/core。終止w/core的含義是:在進程當前目錄生成core文件,並將進程的內存映象復制到core文件中,core文件的默認名稱就是“core”(這是 Unix類系統的一個由來已久的功能)。
事實上,並不是只有SIGSEGV信號產生coredump,還有下面一些信號也產生coredump:SIGABRT(異常終止)、SIGBUS(硬件故障)、SIGEMT(硬件故障)、SIGFPE(算術異常)、SIGILL(非法硬件指令)、SIGIOT(硬件故障),SIGQUIT,SIGSYS(無效系統調用),SIGTRAP(硬件故障)等。Linux系統中在應用程序運行過程中經常會遇到程序突然崩潰,提示:Segmentation fault,這是因為應用程序收到了SIGSEGV信號。這個信號提示當進程發生了無效的存儲訪問,當接收到這個信號時,缺省動作是:終止w/core。終止w/core的含義是:在進程當前目錄生成core文件,並將進程的內存映象復制到core文件中,core文件的默認名稱就是“core”(這是 Unix類系統的一個由來已久的功能)。
事實上,並不是只有SIGSEGV信號產生coredump,還有下面一些信號也產生coredump:SIGABRT(異常終止)、SIGBUS(硬件故障)、SIGEMT(硬件故障)、SIGFPE(算術異常)、SIGILL(非法硬件指令)、SIGIOT(硬件故障),SIGQUIT,SIGSYS(無效系統調用),SIGTRAP(硬件故障)等。對於resouce limit的讀取修改,有兩種方法。

* 使用shell內建命令ulimit
* 使用getrlimit和setrlimit APIsetrlimit:

復制代碼
if (getrlimit(RLIMIT_CORE, &rlim)==0) {
  rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
  if (setrlimit(RLIMIT_CORE, &rlim_new)!=0) {
    rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max;
    (void) setrlimit(RLIMIT_CORE, &rlim_new);
  }
}
復制代碼

 

 

 

Linux上Core Dump文件的形成和分析

Core,又稱之為Core Dump文件,是Unix/Linux操作系統的一種機制,對於線上服務而言,Core令人聞之色變,因為出Core的過程意味着服務暫時不能正常響應,需要恢復,並且隨着吐Core進程的內存空間越大,此過程可能持續很長一段時間(例如當進程占用60G+以上內存時,完整Core文件需要15分鍾才能完全寫到磁盤上),這期間產生的流量損失,不可估量。

凡事皆有兩面性,OS在出Core的同時,雖然會終止掉當前進程,但是也會保留下第一手的現場數據,OS仿佛是一架被按下快門的相機,而照片就是產出的Core文件。里面含有當進程被終止時內存、CPU寄存器等信息,可以供后續開發人員進行調試。

 

關於Core產生的原因很多,比如過去一些Unix的版本不支持現代Linux上這種GDB直接附着到進程上進行調試的機制,需要先向進程發送終止信號,然后用工具閱讀core文件。在Linux上,我們就可以使用kill向一個指定的進程發送信號或者使用gcore命令來使其主動出Core並退出。如果從淺層次的原因上來講,出Core意味着當前進程存在BUG,需要程序員修復。從深層次的原因上講,是當前進程觸犯了某些OS層級的保護機制,逼迫OS向當前進程發送諸如SIGSEGV(即signal 11)之類的信號, 例如訪問空指針或數組越界出Core,實際上是觸犯了OS的內存管理,訪問了非當前進程的內存空間,OS需要通過出Core來進行警示,這就好像一個人身體內存在病毒,免疫系統就會通過發熱來警示,並導致人體發燒是一個道理(有意思的是,並不是每次數組越界都會出Core,這和OS的內存管理中虛擬頁面分配大小和邊界有關,即使不出Core,也很有可能讀到臟數據,引起后續程序行為紊亂,這是一種很難追查的BUG)。

說了這些,似乎感覺Core很強勢,讓人感覺缺乏控制力,其實不然。控制Core產生的行為和方式,有兩個途徑:

1.修改/proc/sys/kernel/core_pattern文件,此文件用於控制Core文件產生的文件名,默認情況下,此文件內容只有一行內容:“core”,此文件支持定制,一般使用%配合不同的字符,這里羅列幾種:

%p  出Core進程的PID
%u  出Core進程的UID
%s  造成Core的signal號
%t  出Core的時間,從1970-01-0100:00:00開始的秒數
%e  出Core進程對應的可執行文件名

2.Ulimit –C命令,此命令可以顯示當前OS對於Core文件大小的限制,如果為0,則表示不允許產生Core文件。如果想進行修改,可以使用:

Ulimit –cn

其中n為數字,表示允許Core文件體積的最大值,單位為Kb,如果想設為無限大,可以執行:

Ulimit -cunlimited

產生了Core文件之后,就是如何查看Core文件,並確定問題所在,進行修復。為此,我們不妨先來看看Core文件的格式,多了解一些Core文件。

首先可以明確一點,Core文件的格式ELF格式,這一點可以通過使用readelf -h命令來證實,如下圖:

 

從讀出來的ELF頭信息可以看到,此文件類型為Core文件,那么readelf是如何得知的呢?可以從下面的數據結構中窺得一二:

 

其中當值為4的時候,表示當前文件為Core文件。如此,整個過程就很清楚了。

了解了這些之后,我們來看看如何閱讀Core文件,並從中追查BUG。在Linux下,一般讀取Core的命令為:

gdb exec_file core_file

使用GDB,先從可執行文件中讀取符號表信息,然后讀取Core文件。如果不與可執行文件攪合在一起可以嗎?答案是不行,因為Core文件中沒有符號表信息,無法進行調試,可以使用如下命令來驗證:

Objdump –x core_file | tail

我們看到如下兩行信息:

SYMBOL TABLE:

no symbols

表明當前的ELF格式文件中沒有符號表信息。

為了解釋如何看Core中信息,我們來舉一個簡單的例子:

#include “stdio.h”

int main(){

int stack_of[100000000];

int b=1;

int* a;

*a=b;

}

這段程序使用gcc –g a.c –o a進行編譯,運行后直接會Core掉,使用gdb a core_file查看棧信息,可見其Core在了這行代碼:

int stack_of[100000000];

原因很明顯,直接在棧上申請如此大的數組,導致棧空間溢出,觸犯了OS對於棧空間大小的限制,所以出Core(這里是否出Core還和OS對棧空間的大小配置有關,一般為8M)。但是這里要明確一點,真正出Core的代碼不是分配棧空間的int stack_of[100000000], 而是后面這句int b=1, 為何?出Core的一種原因是因為對內存的非法訪問,在上面的代碼中分配數組stack_of時並未訪問它,但是在其后聲明變量並賦值,就相當於進行了越界訪問,繼而出Core。為了解釋得更詳細些,讓我們使用gdb來看一下出Core的地方,使用命令gdb a core_file可見:

 

可知程序出現了段錯誤“Segmentation fault”, 代碼是int b=1這句。我們來查看一下當前的棧信息:

 

其中可見指令指針rip指向地址為0×400473, 我們來看下當前的指令是什么:

 

這條movl指令要把立即數1送到0xffffffffe8287bfc(%rbp)這個地址去,其中rbp存儲的是幀指針,而0xffffffffe8287bfc很明顯是一個負數,結果計算為-400000004。這就可以解釋了:其中我們申請的int stack_of[100000000]占用400000000字節,b是int類型,占用4個字節,且棧空間是由高地址向低地址延伸,那么b的棧地址就是0xffffffffe8287bfc(%rbp),也就是$rbp-400000004。當我們嘗試訪問此地址時:

 

可以看到無法訪問此內存地址,這是因為它已經超過了OS允許的范圍。

下面我們把程序進行改進:

#include “stdio.h”

int main(){

int* stack_of = malloc(sizeof(int)*100000000);

int b=1;

int* a;

*a=b;

}

使用gcc –O3 –g a.c –o a進行編譯,運行后會再次Core掉,使用gdb查看棧信息,請見下圖:

 

可見BUG出在第7行,也就是*a=b這句,這時我們嘗試打印b的值,卻發現符號表中找不到b的信息。為何?原因在於gcc使用了-O3參數,此參數可以對程序進行優化,一個負面效應是優化過程中會舍棄部分局部變量,導致調試時出現困難。在我們的代碼中,b聲明時即賦值,隨后用於為*a賦值。優化后,此變量不再需要,直接為*a賦值為1即可,如果匯編級代碼上講,此優化可以減少一條MOV語句,節省一個寄存器。

此時我們的調試信息已經出現了一些扭曲,為此我們重新編譯源程序,去掉-O3參數(這就解釋了為何一些大型軟件都會有debug版本存在,因為debug是未經優化的版本,包含了完整的符號表信息,易於調試),並重新運行,得到新的core並查看,如下圖:

 

這次就比較明顯了,b中的值沒有問題,有問題的是a,其指向的地址是非法區域,也就是a沒有分配內存導致的Core。當然,本例中的問題其實非常明顯,幾乎一眼就能看出來,但不妨礙它成為一個例子,用來解釋在看Core過程中,需要注意的一些問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM