前言
C++服务器经常要分析core文件, 找到错误问题
正文
一, vim
1, vim的配置
set nu // 在左侧行号
set tabstop //tab 长度设置为 4
set nobackup //覆盖文件时不备份
set cursorline //突出显示当前行
set ruler //在右下角显示光标位置的状态行
set autoindent //自动缩进
set stal=2 //显示文件名
2, vim使用
1, 行首 : o 行未: $
2, 文件的首: gg 文件的未 : 大G
3, 查询多少行 : ?G 列子: 220G
4, 删除前一个: x 删除后面一个 : 大X
5, d + o , d + $ , d + d , n + d
6,粘贴: p (下一行) 大P (当前行)
7,复制: yy nyy (n行)
8,可视行 : v
9, 查找 : / ?
10, 高亮: #
11, 替换: r
12, shouj : << >>
13: 查看文档: n + 大k (K) n(第几章)
14:创建一行: o(下面一行) 大o (上面一行)
15: 删除 s(一个字) 大S (整行)
16:水平分屏:sp vsp
二, gdb
1,core的信号
core的信号处理方式:终止进程+产生core文件
- 设置生成core:ulimit -c unlimited
- 取消生成core:ulimit-c 0
2,gdb调试的使用
①, 生成core文件名称(正常开放中使用不到)
设置core文件格式:/proc/sys/kernel/core_pattern
文件不能vi,可以用后面的套路 ,使用root权限 echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
参数说明:
以下是参数列表 :
%p - insert pid into filename 添加 pid
%u - insert current uid into filename 添加当前 uid
%g - insert current gid into filename 添加当前 gid
%s - insert signal that caused the coredump into the filename 添加导致产生 core 的信号
%t - insert UNIX time that the coredump occurred into filename 添加 core 文件生成时的 unix 时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名
②, core文件查询程序断点错误(开放中经常使用)
看这个core文件要是程序员的经验水平越高分析问题越快
参数列表
命令 | 命令缩写 | 命令说明 |
---|---|---|
list | l | 显示多行源代码 |
break | b | 设置断点,程序运行到断点的位置会停下来 |
info | i | 描述程序的状态 |
run | r | 开始运行程序 |
display | disp | 跟踪查看某个变量,每次停下来都显示它的值 |
step | s | 执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句 |
next | n | 执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句) |
p | 打印内部变量值 | |
continue | c | 继续程序的运行,直到遇到下一个断点 |
set var name | =v | 设置变量的值 |
start | st | 开始执行程序,在main函数的第一条语句前面停下来 |
file | 文件名 | 装入需要调试的程序 |
kill | k | 终止正在调试的程序 |
watch | x | 监视变量值的变化 |
backtrace | bt | 产看函数调用信息(堆栈) |
frame | f | 查看栈帧 |
quit | q | 退出GDB环境 |
#!/bin/bash
# 挂载进程
gdb attach PID
# show threads
info threads
# 切换线程
thread 3
# 设置断点
# 在main.cpp文件第100行处为所有经过这里的线程设置断点。
break main.cpp:100
# break main.cpp:100 thread all --> [ERROR]
#backtrace 查看当前运行到第几行。
backtrace
# finsh推出当前调试的函数
#finsh
# 执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句
step
#执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)
next
#detach
detach
# 调试
#set scheduler-locking off|on|step,这个是问得最多的。在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。
#off 不锁定任何线程,也就是所有线程都执行,这是默认值。
#on 只有当前被调试程序会执行。
#step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。
简单的事例
#include <cstdio>
#include <cstdlib>
#include <cstring>
int main(int argc, char *argv[])
{
const char * str = "llllllllllll";
void *p = malloc(343);
if (p)
{
free(p);
p = NULL;
}
// 非法内存访问 str
void * ptr = memcpy(p, str, strlen(str));
if (!ptr)
{
printf("memcpy error\n");
}
return 0;
}
gdb 二进制文件 core
3, 查看 进程的文件描述符
- 设置文件描述符命令
ulimit -n 999999
- 查看每一个进程的信息
ls -la /proc/32189/fd
4, ps -aux命令详解
Linux ps aux指令詳解
①, linux上进程有5种状态:
- 运行(正在运行或在运行队列中等待)
- 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
- 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
- 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
- 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)
②, ps 参数
- ps a 显示现行终端机下的所有程序,包括其他用户的程序。
- ps -A 显示所有程序。
- ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
- ps -e 此参数的效果和指定”A”参数相同。
- ps e 列出程序时,显示每个程序所使用的环境变量。
- ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
- ps -H 显示树状结构,表示程序间的相互关系。
- ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
- ps s 采用程序信号的格式显示程序状况。
- ps S 列出程序时,包括已中断的子程序资料。
- ps -t <终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。终端机编号>
- ps u 以用户为主的格式来显示程序状况。
- ps x 显示所有程序,不以终端机来区分。
- ps -l 較長,較詳細的顯示該PID的信息
ps -lA |more
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 76 0 - 1193 109952 ? 00:00:03 init
1 S 0 2 1 0 -40 - - 0 migrat ? 00:00:03 migration/0
1 S 0 3 1 0 94 19 - 0 ksofti ? 00:00:00 ksoftirqd/0
1 S 0 4 1 0 -40 - - 0 migrat ? 00:00:02 migration/1
1 S 0 5 1 0 94 19 - 0 ksofti ? 00:00:00 ksoftirqd/1
1 S 0 6 1 0 -40 - - 0 migrat ? 00:00:02 migration/2
1 S 0 7 1 0 94 19 - 0 ksofti ? 00:00:00 ksoftirqd/2
相關信息的意義:
F 進程的標誌(flag),4表示用戶為超級用戶
S 進程的狀態(stat),各STAT的意義見下文
PID 進程的ID
C CPU使用資源的百分比
PRI priority(優先級)的縮寫,
NI Nice值,
ADDR 核心功能,指出該進程在內存的那一部分,如果是運行的進程,一般都是“-”
SZ 用掉的內存的大小
WCHAN 當前進程是否正在運行,若為“-”表示正在運行
TTY 登陸者的終端位置
TIME 用掉的CPU的時間
CMD 所執行的指令
# ps aux |more
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4772 564 ? S Sep22 0:03 init [3]
root 2 0.0 0.0 0 0 ? S Sep22 0:03 [migration/0]
root 3 0.0 0.0 0 0 ? SN Sep22 0:00 [ksoftirqd/0]
root 4 0.0 0.0 0 0 ? S Sep22 0:02 [migration/1]
root 5 0.0 0.0 0 0 ? SN Sep22 0:00 [ksoftirqd/1]
root 6 0.0 0.0 0 0 ? Ss+ Sep22 0:02 [migration/2]
root 7 0.0 0.0 0 0 ? SN Sep22 0:00 [ksoftirqd/2]
root 8 0.0 0.0 0 0 ? S Sep22 0:00 [migration/3]
root 9 0.0 0.0 0 0 ? SN Sep22 0:00 [ksoftirqd/3]
root 10 0.0 0.0 0 0 ? S< Sep22 0:00 [migration/4]
上述各位解释:
参数 | 说明 |
---|---|
USER | 进程的属主; |
PID | 进程的ID; |
PPID | 父进程; |
%CPU | 进程占用的CPU百分比; |
%MEM | 占用内存的百分比; |
NI | 进程的NICE值,数值大,表示较少占用CPU时间; |
VSZ | 进程使用的虚拟內存量(KB); |
RSS | 该进程占用的固定內存量(KB)(驻留中页的数量); |
TTY | 该进程在那個終端上運行(登陸者的終端位置),若與終端無關,則顯示(?)。若为pts/0等,则表示由网络连接主机进程 |
WCHAN | 当前进程是否正在進行,若为-表示正在進行; |
START | 該進程被觸發启动时间; |
TIME | 該进程實際使用CPU運行的时间; |
COMMAND | 命令的名称和参数; |
STAT | 狀態位常見的狀態字符 |
STAT狀態字符:
D 无法中断的休眠状态(通常 IO 的进程);
R 正在运行可中在队列中可过行的;
S 处于休眠状态;
T 停止或被追踪;
W 进入内存交换 (从内核2.6开始无效);
X 死掉的进程 (基本很少見);
Z 僵尸进程;
< 优先级高的进程
N 优先级较低的进程
L 有些页被锁进内存;
s 进程的领导者(在它之下有子进程);
l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads);
+ 位于后台的进程组;
configure配置:
./configure –enable-shared=no –enable-static=yes
cmake配置:
cmake -DBUILD_SHARED_LIBS=NO -DCMAKE_BUILD_TYPE=release
Windows
vs2015 x64编译器为例,cmake命令如下:
Xml代码 收藏代码
cmake -G “Visual Studio 14 Win64” path\to\source\dir
去掉Win64,就是32bit:
Xml代码 收藏代码 cmake -G “Visual Studio 14” path\to\source\dir
另外一种等价方式,用命令行参数-A来指定架构(x64或者ARM):
Xml代码 收藏代码 cmake -A x64 path\to\source\dir
结语
总要讲core文件 分析找错误分析