91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

linux程序莫名異常怎么查

發布時間:2020-06-16 18:14:05 來源:網絡 閱讀:8476 作者:鄔領東 欄目:編程語言

內存異常經常導致程序出現莫名其妙的錯誤,往往很難查證,本文介紹在linux下的各種常見內存異常的查證工具和方法。

1 訪問空指針/未初始化指針/重復釋放內存

對于像訪問空指針、未初始化指針(非法地址),重復釋放內存等內存異常,linux默認會拋異常。

比如下面代碼有空指針訪問,編譯運行后會coredump

int main()
{
    int *p=0;
    *p=6;
    return 0;
}

對于此類問題,我們只要在gcc編譯程序時加入-g選項,同時在運行時能夠生成coredump文件,利用gdb就可以定位到具體的問題代碼行。

1.1 開啟coredump

**ulimit -c  unlimited** //unlimited表示不限制coredump文件大小,也可指定一個具體值來限制文件最大長度。

1.2 定制core文件名

默認的coredump文件名為core,如果想自己定制core文件名,可以運行如下命令:

**echo "./core-%e-%p-%t" > /proc/sys/kernel/core_pattern** 

可以在core_pattern模板中使用變量還很多,見下面的列表:

%% 單個%字符

%p 所dump進程的進程ID

%u 所dump進程的實際用戶ID

%g 所dump進程的實際組ID

%s 導致本次core dump的信號

%t core dump的時間 (由1970年1月1日計起的秒數)

%h 主機名

%e 程序文件名

1.3 使用gdb定位代碼行

通過gdb即可定位出錯代碼行

root@ubuntu:/home/zte/test# gcc null.cc -g
root@ubuntu:/home/zte/test# ./a.out 
Segmentation fault (core dumped)
root@ubuntu:/home/zte/test# gdb a.out core
.......
Core was generated by `./null'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000004004fd in main () at null.cc:4
4    *p=6;

2、函數棧溢出

局部變量的寫越界可能會破壞函數棧導致程序出現各種異常行為,但是OS默認不會在越界的第一現場coredump,因此導致問題查證非常困難。

幸運的是我們可以通過gcc的編譯選項-fstack-protector 和 -fstack-protector-all在函數棧被破壞的函數返回時拋異常,從而可以很方便地定位問題所在函數。

代碼示例

int main()
{
    int a=5;
    int *p=&a;
    p[3]=6;
    return 0;
}


上面代碼會破壞函數棧,如果我們用gcc直接編譯運行,不會拋異常。但是加了編譯參數-fstack-protector 和 -fstack-protector-all后,再運行就會拋異常。下面是具體命令執行結果。

root@ubuntu:/home/zte/test# gcc t.c
root@ubuntu:/home/zte/test# ./a.out 
root@ubuntu:/home/zte/test# gcc t.c -fstack-protector -fstack-protector-all -g
root@ubuntu:/home/zte/test# ./a.out 
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
```
可以進一步用gdb的bt命令定位出問題的函數。
```
root@ubuntu:/home/zte/test# gdb a.out core
。。。。。。。。
Core was generated by `./a.out'.
Program terminated with signal SIGABRT, Aborted.
#0  0x00007f6bcfab5c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007f6bcfab5c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007f6bcfab9028 in __GI_abort () at abort.c:89
#2  0x00007f6bcfaf22a4 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7f6bcfc01d70 "*** %s ***: %s terminated\n")
    at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007f6bcfb8d83c in __GI___fortify_fail (msg=<optimized out>, msg@entry=0x7f6bcfc01d58 "stack smashing detected")
    at fortify_fail.c:38
#4  0x00007f6bcfb8d7e0 in __stack_chk_fail () at stack_chk_fail.c:28
#5  0x00000000004005aa in main () at t.c:7
(gdb) q


3 越界讀寫動態分配內存/讀寫已釋放動態分配內存

動態分配內存讀寫越界、讀寫已釋放動態分配內存系統往往不會拋異常,我們可以使用electric-fence來使得讀寫越界內存/已釋放內存后立刻拋異常,加速問題定位。

3.1 安裝Electric fence

sudo apt-get install electric-fence

3.2 使用Electric fence

下面是越界寫代碼

#include <stdlib.h>
int main()
{
    int *p = (int*)malloc(sizeof(int));
    p[1] = 6;
    return 0;
}


如果使用gcc直接編譯運行,不會拋異常。

我們可以加上參數 -lefence -g編譯后運行,就會拋異常。通過gdb的bt打印即可定位到問題代碼行。

root@ubuntu:/home/zte/test# gcc malloc_read_free.cc -lefence -g
root@ubuntu:/home/zte/test# ./a.out 
  Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
Segmentation fault (core dumped)autogen.sh


4 內存泄漏

C/C++程序經常被內存泄漏問題困擾,本文介紹使用gperftools來快速定位內存泄漏問題。

4.1 安裝gperftools工具

4.1.1 安裝automake

sudo apt-get install automake

4.1.2 編譯安裝libunwind

從https://github.com/libunwind/libunwind/releases下載最新版本的libunwind源碼包

解壓到/usr/local/src目錄

cd 解壓源碼目錄

./autogen.sh

./configure

make -j6

make install

4.1.3 編譯安裝gperftools

從https://github.com/gperftools/gperftools/releases下載最新版本的gperftools源碼包

解壓到/usr/local/src目錄

cd 解壓源碼目錄

./autogen.sh

./configure

make -j6

make install

4.2 內存泄漏檢測

下面是一段簡單的內存泄漏源碼

int main()
{
    int *p = (int*)malloc(sizeof(int));
    return 0;
}

編譯代碼、運行工具檢察內存泄漏,注意設置下

root@ubuntu:/home/zte/# gcc leak.cc -g
root@ubuntu:/home/zte/# env HEAPCHECK=normal LD_PRELOAD=/usr/local/lib/libtcmalloc.so ./a.out 
WARNING: Perftools heap leak checker is active -- Performance may suffer
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 4 bytes in 1 objects
The 1 largest leaks:
*** WARNING: Cannot convert addresses to symbols in output below.
*** Reason: Cannot run 'pprof' (is PPROF_PATH set correctly?)
*** If you cannot fix this, try running pprof directly.
Leak of 4 bytes in 1 objects allocated from:
@ 40053f 
@ 7f334da06f45 
@ 400469 
If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
pprof ./a.out "/tmp/a.out.8497._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --gv
If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks more repeatabl
Exiting with error code (instead of crashing) because of whole-program memory leaks

上面的關鍵的輸入信息是:

Leak of 4 bytes in 1 objects allocated from:

@ 40053f   //內存分配的指令地址

@ 7f334da06f45 

@ 400469 

由于工具沒有直接輸出問題代碼行,我們通過反匯編來定位代碼行:

objdump -S a.out  //反匯編程序

截取匯編代碼如下:

int main()
{
  40052d:55                   push   %rbp
  40052e:48 89 e5             mov    %rsp,%rbp
  400531:48 83 ec 10          sub    $0x10,%rsp
    int *p = (int*)malloc(sizeof(int));
  400535:bf 04 00 00 00       mov    $0x4,%edi
  40053a:e8 f1 fe ff ff       callq  400430 <malloc@plt>
  40053f:48 89 45 f8          mov    %rax,-0x8(%rbp)
    return 0;
  400543:b8 00 00 00 00       mov    $0x0,%eax

我們注意到40053f就是對應代碼行int *p = (int*)malloc(sizeof(int));

至此,內存泄漏的元兇被揪出來了,呵呵。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

太保市| 垦利县| 阿坝县| 古田县| 新野县| 嘉祥县| 闸北区| 托克逊县| 泸州市| 确山县| 桦南县| 郴州市| 东乌| 宁安市| 南阳市| 桃园市| 朔州市| 依兰县| 开化县| 遂川县| 金溪县| 蒙城县| 大连市| 牡丹江市| 松江区| 兴隆县| 泸西县| 隆昌县| 张家港市| 彭阳县| 中山市| 闵行区| 北海市| 枞阳县| 丹棱县| 延边| 南部县| 满洲里市| 赫章县| 睢宁县| 兰西县|