gdb 调试 segment default 问题
原文:http://www.unknownroad.com/rtfm/gdbtut/gdbsegfault.html
We are going to use gdb to figure out why the following program causes a segmentation fault. The program is meant to read in a line of text from the user and print it. However, we will see that in it's current state it doesn't work as expected...
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #include <stdlib.h> int main( int argc, char **argv) { char *buf; buf = malloc (1<<31); fgets (buf, 1024, stdin); printf ( "%s\n" , buf); return 1; } |
The first step is to compile the program with debugging flags:
1 | prompt> gcc -g segfault.c |
Now we run the program:
1 2 3 4 | prompt > a.out Hello World! Segmentation fault prompt > |
This is not what we want. Time to fire up gdb:
1 2 3 4 5 6 7 8 9 | prompt > gdb a.out GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and /or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu" ... ( gdb ) |
We'll just run it and see what happens:
1 2 3 4 5 6 | ( gdb ) run Starting program: /home/dgawd/cpsc/363/a .out test string Program received signal SIGSEGV, Segmentation fault. 0x4007fc13 in _IO_getline_info () from /lib/libc .so.6 |
So we received the SIGSEGV signal from the operating system. This means that we tried to access an invalid memory address. Let's take a backtrace:
1 2 3 4 5 6 | ( gdb ) backtrace #0 0x4007fc13 in _IO_getline_info () from /lib/libc.so.6 #1 0x4007fb6c in _IO_getline () from /lib/libc.so.6 #2 0x4007ef51 in fgets () from /lib/libc.so.6 #3 0x80484b2 in main (argc=1, argv=0xbffffaf4) at segfault.c:10 #4 0x40037f5c in __libc_start_main () from /lib/libc.so.6 |
We are only interested in our own code here, so we want to switch to stack frame 3 and see where the program crashed:
1 2 3 | ( gdb ) frame 3 #3 0x80484b2 in main (argc=1, argv=0xbffffaf4) at segfault.c:10 10 fgets(buf, 1024, stdin) |
We crashed inside the call to fgets. In general, we can assume that library functions such as fgets work properly (if this isn't the case, we are in a lot of trouble). So the problem must be one of our arguments. You may not know that 'stdin' is a global variable that is created by the stdio libraries. So we can assume this one is ok. That leaves us with 'buf':
1 2 | ( gdb ) print buf $1 = 0x0 |
The value of buf is 0x0, which is the NULL pointer. This is not what we want - buf should point to the memory we allocated on line 8. So we're going to have to find out what happened there. First we want to kill the currently-running invocation of our program:
1 2 | ( gdb ) kill Kill the program being debugged? (y or n) y |
Now set a breakpoint on line 8:
1 2 | ( gdb ) break segfault.c:8 Breakpoint 1 at 0x8048486: file segfault.c, line 8. |
Now run the program again:
1 2 3 4 5 | ( gdb ) run Starting program: /home/dgawd/cpsc/363/a .out Breakpoint 1, main (argc=1, argv=0xbffffaf4) at segfault.c:8 8 buf = malloc(1<<31); |
We're going to check the value of buf before the malloc call. Since buf wasn't initialized, the value should be garbage, and it is:
1 2 | ( gdb ) print buf $2 = 0xbffffaa8 "Èúÿ¿#\177\003@t`\001@\001" |
Now step over the malloc call and examine buf again:
1 2 3 4 | ( gdb ) next 10 fgets(buf, 1024, stdin); ( gdb ) print buf $3 = 0x0 |
After the call to malloc, buf is NULL. If you were to go check the man page for malloc, you would discover that malloc returns NULL when it cannot allocate the amount of memory requested. So our malloc must have failed. Let's go back and look at it again:
1 | 7 : buf = malloc(1<<31); |
Well, the value of the expression 1 << 31 (the integer 1 right-shifted 31 times) is 429497295, or 4GB (gigabytes). Very few machines have this kind of memory - mine only has 256MB. So of cousre malloc would fail. Furthermore, we are only reading in 1024 bytes in the fgets call. All that extra space would be wasted, even if we could allocate it. Change the 1<<31 to 1024 (or 1<<9), and the program will work as expected:
1 2 3 4 5 | prompt > Hello World! Hello World! prompt > |
So now you know how to debug segmentation faults with gdb. This is extremely useful (I use it more often then I care to admit). The example also illustrated another very important point: ALWAYS CHECK THE RETURN VALUE OF MALLOC! Have a nice day.
作者:白菜菜白
出处:http://www.cnblogs.com/lvchaoshun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2018-10-05 linux 安装matlab