g++编译源码gdb调试以及出现段错误核心已转存的时候怎么借助core文件解决问题详细视频教程

详细视频讲解教程

GCC是GUN编译器集合(GNU Compiler Collection)可以编译C、C++、JAVA等语言

gcc是C编译器(GCC中的GUN C Compiler)

g++是C++编译器(GCC中的GUN C++ Compiler)

编写源文件 hello.cpp

#include <iostream>

int main() {
    std::cout<<"Enter a nummber: ";
    int nummber ;
    std::cin>>nummber;
    for(int i = 0; i < 10; i ++)
    {
        nummber += i;
        std::cout << "nummber + i = " << nummber << std::endl;
    }
    return 0;
}

编译源文件 hello.cpp

g++ -g hello.cpp -o hello

gdb调试可执行程序hello

gdb hello
run 

在这里插入图片描述

常用gdb命令解析

start开始执行程序,在main函数的第一条语句前面停下来
list显示多行源代码
break 行号设置断点,程序运行到断点的位置会停下来
continue 继续程序的运行,直到遇到下一个断点
print 打印内部变量值
kill终止正在调试的程序
watch在程序中设置一个监测点,监视变量值的变化
display跟踪查看某个变量,每次停下来都显示它的值
delete 行号 删除一个断点或监测点
step执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句
finish 如果已经进入了某函数,而想退出该函数返回到它的调用函数,可使用该命令
next单步执行,不可跟踪到函数内部
jump 在源程序中的另一点开始运行
whatis 变量或函数 显示某个变量或函数的类型
set variable 设置变量的值
backtrace bt 查看函数调用的信息堆栈
backtrace n = bt n
n是一个正整数,表示只打印栈顶上n层的栈信息。
-n表一个负整数,表示只打印栈底下n层的栈信息。
如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。
frame n查看栈帧
n是一个从0开始的整数,是栈中的层编号。
比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
up n
表示向栈的上面移动n层,可以不打n,表示向上移动一层。
down n
表示向栈的下面移动n层,可以不打n,表示向下移动一层。
上面的命令,都会打印出移动到的栈层的信息。
quit退出gdb调试

设置core dump文件的大小不受限制

sudo gedit /etc/security/limits.conf

更改改后如下图所示
在这里插入图片描述

设置core dump文件保存位置和名字格式

sudo gedit /etc/sysctl.conf

添加

kernel.core_pattern = /home/q/下载/core.%e-%p-%t

在这里插入图片描述

%e - insert coredumping executable name into filename
%p - insert pid into filename 添加pid(进程id)
%t - insert UNIX time that the coredump occurred into filename

是更改生效

sudo sysctl -p 

造成segment fault,产生core dump的可能原因

1.内存访问越界
a) 由于使用错误的下标,导致数组访问越界
b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,
将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

2.多线程程序使用了线程不安全的函数

3.多线程读写的数据未加锁保护
对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成core dump

4.非法指针
a) 使用空指针
b) 随意使用指针转换
一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump.

5.堆栈溢出
不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。

模拟 core dump 例子

#include "stdio.h"
int main(void)
{

    printf("hello world! dump core for set value to NULL pointer/n");
    *(char *)0 = 0;
    return 0;
}
g++ -g dump_test.cpp -o dump_test
./dump_test

在这里插入图片描述
生成如下文件
在这里插入图片描述

用gdb查看core文件

发生core dump之后, 用gdb进行查看core文件的内容,
以定位文件中引发core dump的行

gdb [exec file] [core file]
gdb dump_test core.dump_test-6918-1594483613

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_21950671/article/details/107270512