Linux下segment fault的调试
Linux下的段错误(Segmentationfault)产生的原因及调试方法(经典)

Linux下的段错误(Segmentation fault )产生的原因及调试方法(经典)2009-04-05 11:25简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址.一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。
一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了•在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的1)访问系统数据区,尤其是往系统保护的内存地址写数据最常见就是给一个指针以0地址2)内存越界(数组越界,变量类型不一致等)访问到不属于你的内存区域解决方法我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。
实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除。
但是手工除虫”(debug),往往是效率低下且让人厌烦的,本文将就”段错误”这个内存访问越界的错误谈谈如何快速定位这些"段错误”的语句。
下面将就以下的一个存在段错误的程序介绍几种调试方法:1 dummy_function (void)2 {3 unsigned char *ptr = 0x00;4 *ptr = 0x00;5 }67 int main (void)8 {9 dummy_function ();1011 return 0;12 }作为一个熟练的C/C++程序员,以上代码的bug应该是很清楚的,因为它尝试操作地址为0 的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。
SegmentationFault错误原因总结

SegmentationFault错误原因总结 最近在项⽬上遇到了Segmentation Fault的错误,⼀直调试不出来是哪⾥出了问题,对于刚接触嵌⼊式的,也不知道该如何去调试⼀个项⽬,定位内存问题,纠结了好⼏天,好阿红整理下⾃⼰的思路。
从头开始。
以下内容只为整理来⾃⼰使⽤的,⼤多来源于⽹络,感谢⼤家的分享:⼀、什么是“Segmentation fault in Linux”A segmentation fault (often shortened to SIGSEGV) is a particular error condition that can occur during the operation of computer software. A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.On Unix-like operating systems, a process that accesses an invalid memory address receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.就是:所谓的段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是⼀个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运⾏级别,指向的gdt是由以64位为⼀个单位的表,在这张表中就保存着程序运⾏的代码段以及数据段的起始地址以及与此相应的段限和页⾯交换还有程序运⾏级别还有内存粒度等等的信息。
段错误总结

(版权声明:本文欢迎转载,但未经允许不得用于商业目的)
2
Segmentation Fault in Linux
内容提要
本文简单介绍了 Segmentation fault 发生的原因, 结合实 际例子描述了内核向用户态程序发送 SIGSEGV 信号的流 程。 文中以实例回答了常见的一些 SIGSEGV 问 题 ,例如“为 什么函数返回了栈还可以访问?”、“为什么 free()后的内存 仍然 可以使用 ”、“为什 么我遇到的是 SIGSEGV 而不 是 SIGILL 信号”等。最后笔者结合自己的经验,列举了一些预 防 SIGSEGV 的编程习惯,供大家参考。SIGSEGV 严格依赖 操作系统、编译器、硬件平台,本文基于 Linux、GCC、32bit IA32 架构,但对其他平台操作系统也有借鉴意义。
我们引用 wiki 上的一段话来回答这个问题。
A segmentation fault (often shortened to SIGSEGV) is a particular error condition that can occur during the operation of computer software. A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system). Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy. On Unix-like operating systems, a process that accesses an invalid memory address receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.
Linux命令行中的进程调试和错误排查技巧

Linux命令行中的进程调试和错误排查技巧在Linux系统中,进程调试和错误排查是开发者和系统管理员必备的技能之一。
通过命令行界面,可以使用一系列工具和技巧来定位和解决进程中的错误和问题。
本文将介绍一些常用的Linux命令行中的进程调试和错误排查技巧,帮助读者快速定位和修复问题。
1. 进程的状态查看与管理在Linux系统中,可以通过以下命令查看和管理进程的状态:- `ps`:显示当前运行的进程列表。
可以使用`ps aux`命令查看所有进程的详细信息,包括PID(进程ID)、CPU使用率、内存占用等。
- `top`:实时动态显示进程列表和系统资源的使用情况。
按键盘上的`q`退出。
- `kill`:终止一个正在运行的进程。
使用`kill PID`命令,其中PID 是要终止的进程的ID。
- `killall`:终止指定进程名对应的所有进程。
使用`killallprocess_name`命令,其中process_name是要终止的进程名。
2. 进程的跟踪与调试当进程发生错误或异常时,可以使用以下命令进行跟踪和调试:- `strace`:跟踪系统调用和信号的发生情况。
使用`strace -p PID`命令,其中PID是要跟踪的进程ID。
- `gdb`:GNU调试器,可以对正在运行的进程进行调试。
使用`gdb -p PID`命令,其中PID是要调试的进程ID。
3. 日志分析与查看Linux系统中的日志文件记录了系统和各个进程的运行状态和错误信息。
以下是一些常用的日志文件和查看命令:- `/var/log/messages`:包含系统运行过程中的大量信息。
使用`tail -f /var/log/messages`命令实时查看该文件的最新内容。
- `/var/log/syslog`:包含系统日志信息,包括内核和其他系统组件的消息。
使用`tail -f /var/log/syslog`命令实时查看该文件的最新内容。
使用Linux终端进行进程调试和故障排除

使用Linux终端进行进程调试和故障排除进程调试是软件开发和故障排除过程中非常重要的一部分。
在Linux操作系统中,使用终端进行进程调试和故障排除可以提供强大的工具和功能。
本文将介绍如何使用Linux终端进行进程调试和故障排除的步骤和技巧。
一、检查进程状态在进行调试和故障排除之前,我们首先需要检查进程的状态。
我们可以使用Linux终端的一些命令来查看当前运行的进程列表,以及它们的状态和资源使用情况。
1. ps命令ps命令是一个常用的用于显示当前运行进程的命令。
通过在终端中输入下面的命令,可以列出当前运行的进程列表:```ps aux```该命令将显示包括进程ID、父进程ID、CPU使用率、内存使用率等在内的详细信息。
2. top命令top命令是一个交互式的实时进程监视器,它可以显示当前运行的进程和它们的资源使用情况。
在终端中输入下面的命令,可以打开top命令的界面:```top```top命令将显示进程的CPU使用率、内存使用率、进程ID等信息,并按照CPU使用率的高低进行排序。
二、跟踪进程在进行进程调试和故障排除时,我们可能需要跟踪进程的执行情况,以便找到问题所在。
Linux终端提供了一些工具,可以用来跟踪进程的执行和输出。
1. strace命令strace命令可以用于跟踪进程的系统调用和信号。
通过在终端中输入下面的命令,可以跟踪一个进程的执行情况:```strace -p <进程ID>```该命令将显示进程执行时的系统调用和信号。
ltrace命令可以用于跟踪进程的库函数调用。
通过在终端中输入下面的命令,可以跟踪一个进程的库函数调用:```ltrace -p <进程ID>```该命令将显示进程执行时的库函数调用。
三、调试进程在进行进程调试时,我们可能需要在程序中设置断点,以便在特定位置暂停执行,并检查程序的状态和变量值。
Linux终端提供了一些调试工具,可以用来调试进程。
sefmentation fault 生成 dmp linux -回复

sefmentation fault 生成dmp linux -回复标题:解决Linux 中的段错误(Segmentation Fault)并生成转储文件(dmp)引言:在Linux 系统中,段错误(Segmentation Fault)是一种常见的错误类型。
当程序试图访问无效的内存地址或者发生内存访问冲突时,系统将发送一个SIGSEGV 信号,导致程序终止运行。
为了更好地解决段错误问题并进行调试分析,本文将一步一步回答如何生成dmp(转储)文件来捕获程序崩溃时的调试信息。
正文:Step 1:编译程序并添加调试信息在解决段错误问题之前,首先需要为程序添加调试信息。
在编译时,使用-g 选项将调试符号包含到可执行文件中,例如:gcc -g program.c -o programStep 2:运行程序并捕获段错误运行程序时,需要使用ulimit 命令设置core dump 文件的最大大小,以便生成转储文件。
使用以下命令将core dump 文件的最大大小设置为无限:ulimit -c unlimited然后运行程序:./program当程序由于段错误而终止时,系统将生成一个名为core 的转储文件。
Step 3:使用gdb 进行调试使用gdb 工具可以方便地分析生成的转储文件。
首先,运行以下命令以启动gdb 调试器,并加载转储文件和可执行文件:gdb -c core ./program然后,使用bt 命令查看段错误发生时的函数调用栈信息,以确定导致段错误的位置:(gdb) btbt 命令会显示导致段错误的函数调用链。
Step 4:生成dmp 文件除了调试信息,我们还可以创建一个dmp 文件,该文件包含了在崩溃时程序的完整内存快照,帮助进一步分析问题。
首先,使用以下命令保存gdb 调试会话到一个文件中:(gdb) set logging on(gdb) set logging file program.dmp(gdb) set logging overwrite on(gdb) info registers(gdb) x/100i pc(gdb) info all-registers(gdb) x/100xb rsp...(gdb) set logging off以上命令将保存所有寄存器的值,当前指令以及一部分堆栈信息到program.dmp 文件中。
segment fault 数组越界解决方法

segment fault 数组越界解决方法
数组越界是程序中常见的错误之一,它会导致程序崩溃或产生不可预测的结果。
为了解决数组越界问题,我们可以采取以下几种方法:
1. 检查数组边界:在编写代码时,我们应该始终注意数组的边界。
确保数组索
引不超出数组的长度范围。
可以使用条件语句(如if语句)来检查数组索引,以
避免发生越界错误。
2. 使用循环迭代:在对数组进行迭代操作时,我们应该使用循环来确保不会越
界访问数组元素。
可以使用for循环或while循环,以合适的条件来循环迭代数组。
3. 使用try-catch语句:一些编程语言提供了异常处理机制,我们可以使用try-catch语句来捕获并处理数组越界异常。
在try块中访问数组元素,并在catch块中
处理越界异常,以避免程序崩溃。
4. 使用内置函数或库:某些编程语言提供了内置函数或库来处理数组越界问题。
我们可以使用这些功能来快速识别和解决数组越界错误。
无论采取何种方法,解决数组越界问题的关键是在编码过程中要审慎处理数组
边界,并确保我们的代码在任何情况下都不会访问超出数组范围的索引。
这样可以增加程序的稳定性和可靠性,并防止潜在的错误出现。
Segmentation fault in linux

Segmentation Fault in Linux——原因与避免Author:ZX_WING(xing5820@)写在前面的话最近CU(chinaunix)出现了很多问segmentation fault 的帖子,其实这也是个“月经贴”了,泡CU几年,每个月都有人问。
为了减少重复回帖,笔者结合自己的经验,总结了SIGSEGV在Linux中产生的机理,并用实际例子概括哪些编程错误容易引发SIGSEGV。
由于本人经验有限,文中难免有疏漏和错误,请发现的朋友发信到xing5820@ 指正,笔者好即使修改。
(版权声明:本文欢迎转载,但未经允许不得用于商业目的)内容提要本文简单介绍了Segmentation fault发生的原因,结合实际例子描述了内核向用户态程序发送SIGSEGV信号的流程。
文中以实例回答了常见的一些SIGSEGV问题,例如“为什么函数返回了栈还可以访问?”、“为什么free()后的内存仍然可以使用”、“为什么我遇到的是SIGSEGV而不是SIGILL信号”等。
最后笔者结合自己的经验,列举了一些预防SIGSEGV的编程习惯,供大家参考。
SIGSEGV严格依赖操作系统、编译器、硬件平台,本文基于Linux、GCC、32bit IA32架构,但对其他平台操作系统也有借鉴意义。
Revision History日期版本描述2009.12.21 1.0初次发表版本1.什么是“Segmentation fault in Linux”?我们引用wiki上的一段话来回答这个问题。
A segmentation fault(often shortened to SIGSEGV)is a particular error condition that can occur during the operation of computer software.A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access,or attempts to access a memory location in a way that is not allowed (for example,attempting to write to a read-only location,or to overwrite part of the operating system).Segmentation is one approach to memory management and protection in the operating system.It has been superseded by paging for most purposes,but much of the terminology of segmentation is still used, "segmentation fault"being an example.Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.On Unix-like operating systems,a process that accesses an invalid memory address receives the SIGSEGV signal.On Microsoft Windows,a process that accesses invalid memory receives theSTATUS_ACCESS_VIOLATION exception.上述文字没有给出SIGSEGV的定义,仅仅说它是“计算机软件操作过程中的一种错误情况”。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux下的段错误产生的原因及调试方法简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址.一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。
一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了.在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的1)访问系统数据区,尤其是往系统保护的内存地址写数据最常见就是给一个指针以0地址2)内存越界(数组越界,变量类型不一致等)访问到不属于你的内存区域解决方法我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。
实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除。
但是手工“除虫”(debug),往往是效率低下且让人厌烦的,本文将就"段错误"这个内存访问越界的错误谈谈如何快速定位这些"段错误"的语句。
下面将就以下的一个存在段错误的程序介绍几种调试方法:1dummy_function(void)2{3unsigned char*ptr=0x00;4*ptr=0x00;5}67int main(void)8{9dummy_function();1011return0;12}作为一个熟练的C/C++程序员,以上代码的bug应该是很清楚的,因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。
我们尝试编译运行它:xiaosuo@gentux test$./a.out段错误果然不出所料,它出错并退出了。
1.利用gdb逐步查找段错误:这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的可执行程序,所以我们加上“-g-rdynamic"的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下:xiaosuo@gentux test$gcc-g-rdynamic d.cxiaosuo@gentux test$gdb./a.outGNU gdb 6.5Copyright(C)2006Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License, and you arewelcome 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"ing host libthread_db library"/lib/libthread_db.so.1".(gdb)rStarting program:/home/xiaosuo/test/a.outProgram received signal SIGSEGV,Segmentation fault.0x08048524in dummy_function()at d.c:44*ptr=0x00;(gdb)哦?!好像不用一步步调试我们就找到了出错位置d.c文件的第4行,其实就是如此的简单。
从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。
通过进一步的查阅文档(man7signal),我们知道SIGSEGV默认handler的动作是打印”段错误"的出错信息,并产生Core文件,由此我们又产生了方法二。
2.分析Core文件:Core文件是什么呢?The default action of certain signals is to cause a process to terminate andproduce a core dump file,a disk file containing an image of the process's memoryat the time of termination.A list of the signals which cause a process to dumpcore can be found in signal(7).以上资料摘自man page(man5core)。
不过奇怪了,我的系统上并没有找到core文件。
后来,忆起为了渐少系统上的拉圾文件的数量(本人有些洁癖,这也是我喜欢Gentoo的原因之一),禁止了core文件的生成,查看了以下果真如此,将系统的core文件的大小限制在512K大小,再试:xiaosuo@gentux test$ulimit-cxiaosuo@gentux test$ulimit-c1000xiaosuo@gentux test$ulimit-c1000xiaosuo@gentux test$./a.out段错误(core dumped)xiaosuo@gentux test$lsa.out core d.c f.c g.c pango.c test_iconv.c test_regex.ccore文件终于产生了,用gdb调试一下看看吧:xiaosuo@gentux test$gdb./a.out coreGNU gdb 6.5Copyright(C)2006Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License, and you arewelcome 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"ing host libthread_db library"/lib/libthread_db.so.1".warning:Can't read pathname for load map:输入/输出错误. Reading symbols from/lib/libc.so.6...done.Loaded symbols for/lib/libc.so.6Reading symbols from/lib/ld-linux.so.2...done.Loaded symbols for/lib/ld-linux.so.2Core was generated by`./a.out'.Program terminated with signal11,Segmentation fault.#00x08048524in dummy_function()at d.c:44*ptr=0x00;哇,好历害,还是一步就定位到了错误所在地,佩服一下Linux/Unix系统的此类设计。
接着考虑下去,以前用windows系统下的ie的时侯,有时打开某些网页,会出现“运行时错误”,这个时侯如果恰好你的机器上又装有windows的编译器的话,他会弹出来一个对话框,问你是否进行调试,如果你选择是,编译器将被打开,并进入调试状态,开始调试。
Linux下如何做到这些呢?我的大脑飞速地旋转着,有了,让它在SIGSEGV的handler中调用gdb,于是第三个方法又诞生了:3.段错误时启动调试:#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<string.h>void dump(int signo){char buf[1024];char cmd[1024];FILE*fh;snprintf(buf,sizeof(buf),"/proc/%d/cmdline",getpid()); if(!(fh=fopen(buf,"r")))exit(0);if(!fgets(buf,sizeof(buf),fh))exit(0);fclose(fh);if(buf[strlen(buf)-1]=='\n')buf[strlen(buf)-1]='\0';snprintf(cmd,sizeof(cmd),"gdb%s%d",buf,getpid()); system(cmd);exit(0);}voiddummy_function(void){unsigned char*ptr=0x00;*ptr=0x00;}intmain(void){signal(SIGSEGV,&dump);dummy_function();return0;}编译运行效果如下:xiaosuo@gentux test$gcc-g-rdynamic f.cxiaosuo@gentux test$./a.outGNU gdb 6.5Copyright(C)2006Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License, and you arewelcome 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"ing host libthread_db library"/lib/libthread_db.so.1".Attaching to program:/home/xiaosuo/test/a.out,process9563Reading symbols from/lib/libc.so.6...done.Loaded symbols for/lib/libc.so.6Reading symbols from/lib/ld-linux.so.2...done.Loaded symbols for/lib/ld-linux.so.20xffffe410in__kernel_vsyscall()(gdb)bt#00xffffe410in__kernel_vsyscall()#10xb7ee4b53in waitpid()from/lib/libc.so.6#20xb7e925c9in strtold_l()from/lib/libc.so.6#30x08048830in dump(signo=11)at f.c:22#4<signal handler called>#50x0804884c in dummy_function()at f.c:31#60x08048886in main()at f.c:38怎么样?是不是依旧很酷?以上方法都是在系统上有gdb的前提下进行的,如果没有呢?其实glibc为我们提供了此类能够dump栈内容的函数簇,详见/usr/include/execinfo.h(这些函数都没有提供manpage,难怪我们找不到),另外你也可以通过gnu的手册进行学习。