【C++】Debugging Segmentation Faults
2022/9/2 1:25:39
本文主要是介绍【C++】Debugging Segmentation Faults,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
linux下的程序,在遇到空指针解引用、栈错误等原因崩溃时,bash会输出一条:
Segmentation fault(core dump)
如果你看到core dumped字样,并且在目录下也找到了一个叫core的文件,那你可以直接用gdb定位到程序崩溃的位置。但是,我在实践中发现,在我的ubuntu 20.04环境下,程序段错误后找不到core文件。
- 检查是否开启core dump?
先用ulimit -c
,如果看到0,说明没有开core dump。
所以我们输入ulimit -c unlimited
,打开core dump。
再次用ulimit -c
,看到unlimited了,说明core dump打开了。
- ulimit -c已经是unlimited了,怎么还是看不到core文件?
输入命令:
man 5 core
查看手册中的core内容,然后往下翻:
它这里面列举了几条不产生core文件的原因,你可以逐条对照。最有可能的原因是/proc/sys/kernel/core_pattern文件里面把你的core文件发送到别处去了。我的ubuntu系统默认就是这样干的。
然后打开/proc/sys/kernel/core_pattern文件,里面如果不是core的内容,表明它可能把你的core文件发到别的地方去了。那么则可以编辑这个文件,把内容改成core,然后保存。
另外有一种更简洁的方式,执行以下命令:
sudo service apport stop
然后你会发现,core_pattern的内容变为core了,这样core文件就可以正常生成了。
GDB
GDB is a powerful debugger that allows a programmer to step through their code line by line and probe any variable for its value at that step of execution. It has a lot of capability beyond what can be addressed in a simple primer. A very useful cheat sheet that I always have a printed copy of on my desk can be found here https://darkdust.net/files/GDB Cheat Sheet.pdf.
First and foremost, GDB will need some specific information injected into the executable that needs to be debugged. This requires compiling all of our code with the -g
flag. The best way to do this is by adding it to your CXXFLAGS
variable in your Makefile. That ensures that all automatically created *.o files are also built using the -g
flag. You should also delete the old *.o files before rebuilding. This is a great time to run make clean
, assuming you have a well-defined clean
rule in your Makefile.
Now that you have recompiled with -g
flags, you can fire up the debugger. The -tui
flag below opens the source code in the top half of the screen which is great for adding some context to where the program is in the execution. gdb -tui a.out
If files were built with -g
, the symbol table should load and GDB is ready to use. The first thing that is typically needed is to add one or more breakpoints. These can be added to method names, or to lines of code (if you specify a line that cannot break, the next breakable line is used).
Breaking on a specific line of source code
To halt execution at line 12 of test.cpp, you would simply type break test.cpp:12
. Now when you type run
, GDB starts executing and will halt at line 12 (or the next breakable line) so that you can inspect the status of your program.
Breaking on a method
If you suspect a specific method or function in your code, you can halt execution and inspect whenever that method is called. In order to inspect the method Search
within the BinarySearch
class, I would type break BinarySearch::Search(int*, int, int, int)
. As you might have guessed, this is a great time for tab-completion which GDB is great at. Just start typing the class or method name and hit tab in order to fill in the rest. Now when you type run
, GDB starts executing and will halt the first (and every) time that method is called.
Stepping through
The commands needed to restart execution after a breakpoint has been reached are:
next
- This goes to the next line of code, but will not dive into functions.step
- This goes to the next line of instruction. This might be inside of a function call or elsewhere in the code tree.continue
- This runs the program until the end of execution, or until a breakpoint is reached.
Looking at values
The simple act of stepping through code often helps figure out the problem. “This should not go inside that if
statement”…well, it does, so figure out why.
Sometimes, it is not enough to just know the current location of your code execution. Luckily, we can print out values of our variables. print myVar
would print the value of myVar
. print &myVar
would print the address of myVar
. Pointers will print the address by default. To see their value, you would need to dereference, e.g. print *myPointer
. As you might have noticed, the print statement is identical to sticking in std::cout
statements, except that you don’t need to guess in advance, you can poke around until you find the values you need. Print will also let you call methods, so print myObject.GetSomeData()
would print the results of the method call.
When breaking on a method call, the arguments passed to the call are printed automatically. For the BinarySearch breakpoint we mentioned earlier, when the breakpoint is triggered, the output might read:
Breakpoint 1, BinarySearch::Search (listOfNumbers=0x7fffffffc720, left=7, right=10, searchKey=10) at binary-search.cpp:5
参考:
https://stackoverflow.com/questions/2065912/core-dumped-but-core-file-is-not-in-the-current-directory
这篇关于【C++】Debugging Segmentation Faults的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24怎么切换 Git 项目的远程仓库地址?-icode9专业技术文章分享
- 2024-12-24怎么更改 Git 远程仓库的名称?-icode9专业技术文章分享
- 2024-12-24更改 Git 本地分支关联的远程分支是什么命令?-icode9专业技术文章分享
- 2024-12-24uniapp 连接之后会被立马断开是什么原因?-icode9专业技术文章分享
- 2024-12-24cdn 路径可以指定规则映射吗?-icode9专业技术文章分享
- 2024-12-24CAP:Serverless?+AI?让应用开发更简单
- 2024-12-23新能源车企如何通过CRM工具优化客户关系管理,增强客户忠诚度与品牌影响力
- 2024-12-23原创tauri2.1+vite6.0+rust+arco客户端os平台系统|tauri2+rust桌面os管理
- 2024-12-23DevExpress 怎么实现右键菜单(Context Menu)显示中文?-icode9专业技术文章分享
- 2024-12-22怎么通过控制台去看我的页面渲染的内容在哪个文件中呢-icode9专业技术文章分享