gdb
生成core文件的条件
-g // gcc -g main.c -o exe
ulimit -c 1024 // ulimit -a
权限问题:exe文件的拥有者,否则可能不能生成core文件。 // 用root, 不用sudo。sudo没有打印“core dumped"
core文件的相关信息
默认位置:同exe文件的位置,若程序中有chdir(),则有可能改变。
默认名字:core
可以通过 /proc/sys/kernel/core*,等配置文件修改 // echo 1 > core_uses_pid
查看相应的exe文件:
file coreFile
gdb -c coreFile
readelf -h coreFile
利用core分析程序问题:
gdb -c coreFile exeFile
gdb exeFile coreFile
backtrace, bt 2(打印2层栈)
gdb的使用
开启:gdb exeFile
给exe文件传入参数:set args/run -t 5 -i data/rtp.data
查看代码:set/show listsize, list +/-, list 151, list funcName, list 45, 49
(gdb) list wiucs::RecordConvert::convert
打断点:break 151; b filename:151; b WebmMuxer::open;
break 199 if x == 2(x若是局部变量,则需要到此代码处,再打断点)
watch x > 2(x处理同上,x>2的值若有改变,则断点产生)
断点管理:delete 4(断点号), disable/enable 4, clear 151(代码行号), tbreak 151
查看变量:print varName; display/undisplay varName(遇断点时,自动显示);
whatis mediaHead(查看结构体);
set print pretty on
(gdb) p ntohs(seqnum)
控制流程:run, next, step(into func), finish(outof func), continue/until 159,
改流程:return 111, jump 159(直接跳到159行), signal 11(发段错误信息使程序停止执行)
设置值:set variable var_p = (char *)malloc(2) or print var_p = ...
线程:thread 3(切换到线程3);
break 88 thread 3 if x == y // 当线程3执行到88行并且变量x和y值相等时中断
查看信息:where, frame 9(进入9号帧), up / down-silently(上下移动帧),
info locals/args/threads/frame/line(当前帧下的信息)
(gdb) info all-registers 寄存器中放置了程序运行时的数据,比如程序当前运行的指令地址(ip),程序的当前堆栈地址(sp)
(gdb) disassemble func // 打印出汇编代码
gdb问题:
有断点停不下来 // 实际停下来了,只是按continue时,没有返回,又按了一次,导致C两次,断点打印在前面
gcc 寻找头文件
1. 当前文件夹; 2. -I ; 3. /usr/include 4. gcc的环境变量C_INCLUDE_PATH...
#include <系统路径> // 查找顺序 3, 4, 1, 2
#include “对此C文件的路径” // 查找顺序 1,2,3,4
生成静态库
1. gcc -c a.c // 编译成.o
// ar命令中不能加-lXXX, ar: two different operation options specified
2. ar -rcs libXXX.a obj1.o obj2.o (ar=archive, r=replace, c=create, s=)
生成动态库
gcc -fPIC -shared -o libxxx.so a.c b.c
gcc -fPIC -o a.o -c a.c // gcc -c a.c
gcc -shared -o libxxx.so a.o // gcc -fPIC -shared -o libXXX.so a.o
查看库中的内容
ar tv libXXX.a // 查看静态库含有的.o文件
nm -s libXXX.a // 查看静态动态库中的.o以及函数: U引用 T定义 W弱态
ldd libXXX.so // 查看so中的引用的so
库的使用
1. -L; 2. LD_LIBRARY_PATH; 3. /etc/ld.so.conf ---> ldconfig ---> ld.so.cache; 4. /lib, /usr/lib
静态库:编译时寻找的顺序:1,2,3,4; 编译完成后.a的代码集成在exe中,执行时无需.a文件了。
动态库:编译时寻找的顺序同上; 执行时仍然需要.so,其查找顺序为: -Wl,-rpath,/path1/:/path2(无空格,冒号),2,3,4
Q&A
0. LD_LIBRARY_PATH已经包含了动态库所需要的路径,但是程序还是找不到所需要的库
场景1:LD_LIBRARY_PATH=...:A:...:B:...
A,B路径都包含libjvm.so, libjava.so , 但是B=$JAVA_HOME/jre/lib/amd64/
结果:程序只在A中找所有需要的jre库
Error occurred during initialization of VM
Unable to load native library: /opt/wiucs-cvt/libjava.so: cannot open shared object file:
No such file or director
解决方法: A,B位置互换; 或者删除A中的.so
场景2:export LD_LIBRARY_PATH=/tmp;
当前shell调用 httpd, httpd 的子进程执行CGI程序,CGI程序需要新的SO
结果:尽管/tmp下有所需要的动态库,但是CGI仍然引用不到
解决方法:export后仅當前shell(控制台)及其子shell(httpd)可用,CGI是httpd的子进程所以引用不到;
指定执行动态库时的搜索路径:
mips2_fp_le-gcc -o getPageInfo -Wl,-rpath,/tmp $(OBJS) $(LIBS)
1. 多个-l的顺序:根据依赖关系,反序排列!
g++ -o test IsacDecoder.cpp... -I... -L... -liSAC -lCNG -lsignal_processing -lpthread
2. 找不到库中函数:nfs: server is working? // 动态库在nfs server上
3. 程序既要和libhello进行静态连接,又要和libbye进行动态连接,
其命令应为: gcc testlib.o -o exefile -WI,-Bstatic -lhello -WI,-Bdynamic -lbye
-static -lXXX // 强制使用静态库(同时存在,默认动态库优先)
4. 动态库的应用:做插件 plugin // dlopen, dlsym
gcc 命令
gcc -o hello hello.c -save-temps(一步,保留中间文件)
预处理 gcc -o hello.i -E hello.c
编译和汇编 gcc -o hello.o -c hello.i // ccl and as
链接 gcc -o hello hello.o // ld
生成依赖关系 gcc -MM a.c // a.o: a.c; -MMD: 生成.d .o
-Dmacro
相当于C语言中的#define macro
-Dmacro=defn
相当于C语言中的#define macro=defn
调试打印 #gcc -DDLD_DEBUG -O0 -g3 -Wall -c
#ifdef DLD_DEBUG
#define dbprintf(fmtstr, args...) \
{printf(fmtstr, ##args); printf("\n");}
#else
#define dbprintf(fmtstr, args.