linux调试和编译

Posted sunny_ss12

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux调试和编译相关的知识,希望对你有一定的参考价值。

1. 今天在linux使用dlopen打开我编译的一个动态库时发现总是提示失败。

这时可以调用ldd命令查看编译部署的那个动态库依赖库有哪些,是否能找到

我通过调用ldd ./libSyslogAticGatherTask.so (./libSyslogAticGatherTask.so是我编译好的一个动态库名)

发现提示linuxACE.so.6.0.3 => not found,如下图所示。


这里libACE.so.6.0.3应该是一个链接文件,但执行目录中没有这个链接文件,使用ln -s 命令创建一个软链接指向本地libACE-6.0.3.so即可:ln -s ./libACE.so.6.0.3 ./libACE-6.0.3.so

之后调用该动态链接库发现成功。


2.  今天编译另一个动态库,发现总是提示 undefined reference to `ACE_Service_Config::open(int, char**, char const*, bool, bool, bool)。这个函数是ACE的一个函数,但是这个动态库我已经放到指定目录下了,头文件也包含了。也是我进入ACE库目录,然后执行nm ./libACE.so.6.0.3查看它导出的函数,由于它导出的函数很多,我需要查看ACE_Service_Config::open函数的导出情况,于是执行nm ./libACE.so.6.0.3 | grep ACE_Service_Config | grep open,发现结果为:

000000000014d1a0 T _ZN18ACE_Service_Config6open_iEPKcS1_bbb

通过查ACE_Service_Config的源代码,发现这个函数是ACE_Service_Config::open_i函数,而open并没有导出,可是我纳闷了,这个代码是很老的代码,为什么之前的代码没有出现这个问题呢?于是我在生成环境运行nm ./libACE.so.6.0.3 | grep ACE_Service_Config | grep open,发现输出结果为:

0000000000190010 T _ZN18ACE_Service_Config4openEPKcS1_bbb
000000000018ff40 T _ZN18ACE_Service_Config4openEiPPcPKcbbb
000000000018f7d0 T _ZN18ACE_Service_Config6open_iEPKcS1_bbb

可以发现ACE_Service_Config::open函数导出了。之前的ACE库是我自己编译的,可能编译少了某些参数????把生成环境的ACE库放到我的目录下,代码编译成功。


3.1  调试正在运行的程序:

(1)使用ps aux | grep 程序名字:查看程序的进程号

(2)进入运行程序的Bin目录,然后执行gdb ./程序名

(3)进入gdb后,执行attach 程序进程号,即可调该程序

(4)下断点。在需要调试的地方打断点,由于我代码和运行的程序没有放在一个目录下,而且文件嵌套到很长的目录下,我需要使用dir目录设置相对目录。比如我需要在/home/svn/SAC100/trunk/Src/SAC-loginsight/Src/WebSvr/WebSvr.cpp下断点,而所有代码都嵌套到/home/svn/SAC100/trunk/Src/SAC-loginsight/Src了,我需要调用dir /home/svn/SAC100/trunk/Src/SAC-loginsight/Src设置相对目录,然后调用break WebSvr/WebSvr.cpp:209,在WebSvr/WebSvr.cpp处下断点。

(5)由于执行attach后,程序已经停下来了,需要执行c或continue让程序继续跑,当程序运行到WebSvr/WebSvr.cpp的209就停下来了。之后就可以单步调试代码了。

  3.2  调试未执行的进程:(1)gdb ./程序名 (2) break 设置断点 (3)start开始调试  (4)continue:进入断点


4. gdb下修改代码路径:

  在3中,调试代码时,我运行list main,发现总是提示
18 /data/svn/SAC100/trunk/Src/SAC-loginsight/Src/LAGatherServer/LAServer.cpp: No such file or directory

这是因为代码编译后我将代码的位置由/data/svn/SAC100修改为了/home/svn/SAC100,导致gdb总是报No such file or directory的错误,这时可以使用 set substitute-path设置路径替换规则:具体为:set substitute-path /data/svn/SAC100 /home/svn/SAC100,表示告诉gdb在看到/data/svn/SAC100的时候他会做自动替换成/home/svn/SAC100

set substitute-path用来修改相对路径,dir可以修改相对路径,具体可以参考《GDB源代码查找路径》  http://www.cnblogs.com/rickyk/p/4184860.html


5. cmake区分Debug和Release的方法:

在cmake中要编译debug模式的话,在CMakeLists.txt中添加如下两行
SET(CMAKE_CXX_FLAGS_DEBUG "$ENVCXXFLAGS -O0 -Wall -g -ggdb ")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENVCXXFLAGS -O3 -Wall")
然后,在编译的时候,使用如下命令:
cmake -DCMAKE_BUILD_TYPE=Debug/Release  path
第三个参数path是指项目的顶层路径

参考自: 《cmake Debug模式和Release模式》 http://blog.sina.com.cn/s/blog_6b02ec9a0100vahz.html

cmak总结:《linux下cmake编译C++工程之总结篇》 http://blog.csdn.net/boyxiaolong/article/details/24708201

                      《CMAKE的使用》   http://www.cnblogs.com/lidabo/p/3974305.html

6. 查看一个lib或bin是否带有调试信息的方法:

readelf -S libxxx.so |grep debug    

《Linux下查看.so和可执行文件是否debug编译》    http://blog.csdn.net/gong_xucheng/article/details/23996145



以上是关于linux调试和编译的主要内容,如果未能解决你的问题,请参考以下文章

《Linux从0到99》四 Linux编译器(gcc/g++)和调试器(gdb)

FFmpeg之Linux下编译与调试

Linux下的编译调试命令

Linux下gcc编译器和gdb调试

Linux软件安装调试 源代码包编译安装和 二进制包配置

在linux里,c程序的编辑、编译、调试的详细步骤是啥?