NDK程序的调试方法

调试的方法有两种,一种是打log,使用adb logcat命令来查看log信息,另一种就是使用调试器来下断点调试程序




先看打log:


在c代码中打印日志:


#include <android/log.h>
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "ProjectName", __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , "ProjectName", __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , "ProjectName", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ProjectName", __VA_ARGS__)




然后就可以在代码里面使用这些宏来打印日志了。




在android.mk文件中要指示连接log库:


LOCAL_LDLIBS := -llog




在模拟器中运行程序,然后在cmd终端中输入:adb logcat  之后就能实时的看到打印出来的log了

这个logcat程序如果没有使用-c选项,进入之后就不能退出了,要关掉模拟器才能退出,
所以还是在cmd终端中运行这个命令,避免影响cygwin做其他事情。


关于logcat命令是详细使用方法:

adb logcat ActivityManager:I OGRE:D *:S


这个表示只输出OGRE/I, info级别的,这就能捕捉,Ogre里面的LogManager的logMessage()输出的信息。


ogre 开发的android程序就使用这个来俘获输出就好了。






使用GDB调试程序,GDB使用客户端服务器的方式来调试程序,
服务端是连接到电脑的手机,客户端在pc上,服务端控制,手机上的程序运行,
服务端接受并响应来自客户端的命令请求。
客户端通过TCP的一个端口和服务端通信。


要是我们编译的so文件可以调试,需要满足下面这些条件:

   1 使用ndk-build来构建程序,这个命令会帮助你生成gdbserver等文件,用于调试。


   2 设置应用程序为可调试:
你的AndroidManifest.xml拥有<application>元素,它设置android:debuggable属性为true


   3 运行你的应用的android系统版本需大于等于2.2版本。


   还有些注意事项:

如果你使用ADT Eclipse插件构建你的应用程序,请确保你正在使用0.9.7或更新


如果你正在使用ant构建工具,请确保你拥有最新修订版的SDK平台组件。需要以下最小修订版:


                Android 1.5      r4


                Android 1.6      r3


                Android 2.1      r2


                Android 2.2      r1
这些修订版通过SDK更新器可用。


     如果这些条件不满足,所生成的.apk将不包含所需支持文件,并将不可能支持原生调试。




使用ndk-gdb来调试程序,这个命令搜索一个已经运行的程序,如果找不到,会报告错误,
然而你可以使用--start或--launch=<名称>选项以在调试会话前自动开始你的活动。


当它成功地连接到你的应用程序进程,在把会话配置为可以合适地找到你的源文件和

你生成的符号/调试版本的本地库之后,ndk-gdb将给你一个常规的GDB提示符。


GDB提示符之前将出现一长列错误消息,那里gdb解释它不能找到各种系统库
(例如:libc.so,libstdc++.so,liblog.so,libcutils.so,等等)
这是正常的,因为在你的开发机器上这些对应你目标设备的符号/调试版本的库不存在。
你可以安全地忽略这些消息。




然后就可以使用GDB的命令来调试程序了。








下面介绍一些简单的命令:


加载需要调试的so文件的符号表:

使用list或者l可以查看加载的c文件。
如果提示符号表没有加载,则使用file命令加载:
file obj/local/armeabi/libsearch-algorithm.so







下断点:
b 100    表示在第一百行下个断点。


c 继续运行程序




ndk-gdb --help 查看ndk-gdb的用法


--verbose:


    打印出关于原生调试会话配置的详细信息。
只在你不能连接和ndk-gdb打印的错误消息不足时才需要用它来调试问题。


--force:


    默认,如果发现另一个调试会话运行在相同设备,ndk-gdb会中止。
使用--force将杀死那个会话,并且把新的会话替换它。
注意调试的程序不会被杀死并且将再次被停止。


--start:


    默认,ndk-gdb将尝试连接到在目标设备上现存运行的你的应用程序实例。
你可以使用--start显式地在调试会话前启动你的应用程序。


注意:它启动在你的应用程序清单(注:指AndroidManifest.xml?)中列出的第一个可运行活动。
使用--launch=<名称>以开始另一个活动。参考--launch-list以转储这类活动的列表。


--launch=<name>:


    类似于--start,不同的是它允许启动你的应用程序的一个特定活动。
它只在你的清单定义多个可运行活动时才有用。


-launch-list:


    方便选项,打印所有在你的应用程序清单中可启动活动的名称列表。
第一个活动将被--start使用。


--project=<path>:


    指定应用程序工程目录。如果你想在启动脚本前不切换目录,这个选项会有用。


--port=<port>:


    默认,ndk-gdb将使用本地TCP端口5039和调试的应用程序通信。
通过使用一个不同的端口,可以原生地调试运行在连接到相同开发机器的不同设备/模拟器上的多个程序。


--adb=<file>:


    如果adb不在你的PATH搜索路径中,用它指定adb工具的可执行文件。


-d:          连接到单个物理设备
-e:         连接到单个模拟设备
-s <serial>: 连接到特定设备或模拟器,这里<serial>是adb devices命令中列出的设备名称。


--exec=<file>:
  -x <file>:


    在能连接到调试进程后,运行在<file>文件中的GDB初始化命令。
如果你想重复地做一些事情时有用,例如设置一列断点然后自动地恢复执行。


关于多线程的调试:


如果你的应用程序运行在一个比Android 2.3更新的平台上,ndk-gdb将不能合理地调试原生线程。
相反,调试器将只能在主线程放置断点,完全忽略其它线程的执行。

问题的根源很复杂,但本质上是因为平台上的一个非常不幸的缺陷,它较迟被发现。


来自NDK的gdbserver二进制文件拥有特殊代码在运行期检测这个条件并自动地适配它的行为
换句话说,当你构建你的代码时,你不需要做任何特殊的事情


用实际的话来说这意味着:
如果你在Android 2.3或之前的平台发布版上,它已经被针对老版本的补丁作出平台修正,
那么你将可以自动地可以调试原生多线程


如果你不是,你将只能调试主线程(正如以前的NDK发布版那样)。
你还将在启动ndk-gdb时看到以下消息(值出现在gdb提示符前):
在这个Android平台上不支持线程调试!


如果你在非主线程上执行的函数放置一个断点,GDB将用以下消息退出程序:
Program terminated with signal SIGTRAP, Trace/breakpoint trap. The program no longer exists.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值