android ndk 調試項目

調試項目

在構建應用后,您可能需要對其進行調試候引。本節(jié)介紹 NDK 的調試工具邓尤。

首先介紹如何使用 ndk-gdb 工具調試代碼。 最后說明 ndk-stack 工具剩檀,該工具可幫助您在調試時使用 ADB logcat 工具憋沿。

ndk-gdb

NDK 包含一個名為 ndk-gdb 的幫助程序 shell 腳本,可輕松地為 NDK 生成的機器代碼啟動原生調試會話沪猴。

要求

要運行原生調試辐啄,您必須遵循以下要求:

  • 使用 ndk-build 腳本構建您的應用。ndk-gdb 腳本不支持使用舊的 make APP=<name>方法進行構建运嗜。
  • 通過添加一個將 android:debuggable 屬性設置為 true<application> 元素壶辜,在 AndroidManifest.xml 文件中啟用應用調試。
  • 構建在 Android 2.2(Android API 級別 8)或更高版本上運行的應用担租。
  • 在運行 Android 2.2 或更高版本的設備或模擬器上進行調試砸民。 在 AndroidManifest.xml文件中聲明的 API 級別對于調試并不重要。
  • 在 Unix shell 中開發(fā)您的應用奋救。在 Windows 上岭参,使用 Cygwin 或實驗性 ndk-gdb-pyPython 實現。
  • 使用 GNU Make 3.81 或更高版本菠镇。

用法

如需調用 ndk-gdb 腳本冗荸,切換到應用目錄或該目錄下面的任何目錄。 例如:

<pre class="no-pretty-print" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: "Roboto Mono", monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">cd PROJECTNDK/ndk-gdb
</pre>

此處利耍,$PROJECT 指向項目的根目錄蚌本,$NDK 指向 NDK 安裝路徑。

調用 ndk-gdb 時隘梨,它配置此會話以查找源文件和生成的原生庫的符號/調試版本程癌。 成功附加到您的應用進程后,ndk-gdb 將輸出一長串錯誤消息轴猎,表示其無法找到各種系統(tǒng)庫嵌莉。 這很正常,因為您的主機不包含您的目標設備上的這些庫的符號/調試版本捻脖。 您可以完全忽略這些消息锐峭。

接下來,ndk-gdb 顯示一個正常的 GDB 提示可婶。

您使用與 GNU GDB 交互的方式與 ndk-gdb 進行交互沿癞。例如,您可以使用 b <location> 設置斷點矛渴,使用 c(表示“continue”)繼續(xù)執(zhí)行椎扬。 有關完整的命令列表,請參閱 GDB 手冊

請注意蚕涤,當您退出 GDB 提示時筐赔,您正在調試的應用進程將停止。此行為是 gdb 的一個局限揖铜。

ndk-gdb 可處理許多錯誤情況茴丰,如果它發(fā)現問題,將顯示信息性錯誤消息天吓。這些檢查包括確保符合以下條件:

  • 確保 ADB 位于您的路徑中较沪。
  • 確保您的應用在其清單中聲明為可調試。
  • 確保設備上安裝的具有相同軟件包名稱的應用同樣可調試失仁。

默認情況下尸曼,ndk-gdb 搜索一個已運行的應用進程,如果未找到萄焦,則顯示錯誤控轿。 不過,您可以使用 --start--launch=<name> 選項在調試會話前自動啟動您的 Activity拂封。 如需了解詳細信息茬射,請參閱選項

選項

若要查看完整的選項列表冒签,請在命令行上鍵入 ndk-gdb --help在抛。表 1 顯示了許多比較常用的選項及其簡要說明。

表 1. 常用 ndk-gdb 選項及其說明萧恕。

通過這個指定的選項啟動 ndk-gdb 將啟動應用清單中列出的第一個可啟動 Activity刚梭。 使用 --launch=<name> 來啟動下一個可啟動 Activity。 若要轉儲可啟動 Activity 的列表票唆,請從命令行運行 --launch-list朴读。

| 選項 | 說明> |
| --verbose |

此選項指示構建系統(tǒng)打印有關原生調試會話設置的詳細信息。 僅在調試程序無法連接到應用走趋,且 ndk-gdb 顯示的錯誤消息不充分時才需要用它調試問題衅金。

|
| --force | 默認情況下,如果 ndk-gdb 發(fā)現另一個原生調試會話已在相同設備上運行簿煌,它將會取消運行氮唯。 此選項將終止另一個會話,并將其替換為新的會話姨伟。 請注意惩琉,此選項不會終止正在調試的實際應用,您必須另行終止它授滓。 |
| --start |

當您啟動 ndk-gdb 時琳水,默認情況下,它嘗試附加到目標設備上您的應用已運行的實例般堆。 您可以替換此默認行為在孝,在調試會話前使用 --start 在目標設備上顯式啟動應用。

|
| --launch=<name> |

此選項類似于 --start淮摔,不過它允許您從應用啟動特定 Activity私沮。 僅當您的清單定義多個可啟動 Activity 時,才可使用該功能和橙。

|
| --launch-list |

這個便捷選項打印在您的應用清單中找到的所有可啟動 Activity 名稱的列表仔燕。--start 使用第一個 Activity 名稱。

|
| --project=<path> | 此選項指定應用項目目錄魔招。如果您希望不必先切換到項目目錄就可啟動腳本晰搀,則該選項很有用。 |
| --port=<port> |

默認情況下办斑,ndk-gdb 使用本地 TCP 端口 5039 與它在目標設備上調試的應用進行通信外恕。 使用不同的端口讓您可以在本地調試連接至相同主機的不同設備或模擬器上運行的程序。

|
| --adb=<file> |

此選項指定 adb 工具可執(zhí)行文件乡翅。 只有在您未設置包括該可執(zhí)行文件的路徑時才需要使用此選項鳞疲。

|
| * -d* -e* -s <serial> |

這些標志與具有相同名稱的 adb 命令類似。如果您有連接至主機的多個設備或模擬器蠕蚜,請設置這些標志尚洽。 其含義如下所示:

<dl style="box-sizing: inherit; margin: 0px; padding: 0px;">

<dt style="box-sizing: inherit; font-style: normal; font-variant: normal; font-weight: 700; font-stretch: normal; font-size: 16px; line-height: 24px; font-family: Roboto, sans-serif; margin: 16px 0px;">-d</dt>

<dd style="box-sizing: inherit; margin: 16px 0px; padding: 0px 0px 0px 20px;">連接至單個物理設備。</dd>

<dt style="box-sizing: inherit; font-style: normal; font-variant: normal; font-weight: 700; font-stretch: normal; font-size: 16px; line-height: 24px; font-family: Roboto, sans-serif; margin: 16px 0px;">-e</dt>

<dd style="box-sizing: inherit; margin: 16px 0px; padding: 0px 0px 0px 20px;">連接至單個模擬器設備靶累。</dd>

<dt style="box-sizing: inherit; font-style: normal; font-variant: normal; font-weight: 700; font-stretch: normal; font-size: 16px; line-height: 24px; font-family: Roboto, sans-serif; margin: 16px 0px;">-s <serial></dt>

<dd style="box-sizing: inherit; margin: 16px 0px; padding: 0px 0px 0px 20px;">連接至特定設備或模擬器腺毫。此處,<serial> 是設備的名稱(如 adb devices 命令所列出)挣柬。</dd>

</dl>

或者拴曲,您可以定義 ADB_SERIAL 環(huán)境變量以列出特定的設備,無需具體的選項凛忿。

|
| * --exec=<file>* -x <file> |

此選項指示 ndk-gdb 在連接至它正在調試的進程后運行在 <file> 中找到的 GDB 初始化命令澈灼。 如果您要重復執(zhí)行某些操作,如設置斷點列表店溢,然后繼續(xù)自動執(zhí)行叁熔,則該功能很有用。

|
| --nowait |

停用暫停 Java 代碼床牧,直到連上 GDB荣回。傳遞此選項可能會使調試程序錯過早期的斷點。

|
| --tui -t |

啟用 Text User Interface(如果可用)戈咳。

|
| --gnumake-flag=<flag> |

此選項是在查詢 ndk-build 系統(tǒng)以獲取項目信息時要傳遞到該系統(tǒng)的額外標志(或多個標志)心软。 您可以在同一個命令中使用此選項的多個實例壕吹。

|
| --stdcxx-py-pr={auto|<wbr style="box-sizing: inherit;">none|<wbr style="box-sizing: inherit;">gnustdcxx[-GCCVER]|<wbr style="box-sizing: inherit;">stlport} |

在 C++ 標準庫中使用指定的 Python pretty-printer 顯示相應類型。auto 模式通過查看用于 libstdc++ 庫的.so 文件運行删铃,因此耳贬,該模式僅適用于共享庫。 以靜態(tài)方式鏈接到 libstdc++ 庫時猎唁,您必須指定所需的打印機咒劲。 默認值為 none

|

注:此表中的最后三個選項僅適用于 ndk-gdb 的 Python 版本诫隅。

線程支持

如果您的應用在 Android 2.3(API 級別 9)以前的版本上運行腐魂,則 ndk-gdb 無法正確調試原生線程。 調試程序只能調試主線程逐纬,abd 完全忽略其他線程的執(zhí)行蛔屹。

如果您在非主線程上執(zhí)行的函數上放置一個斷點,則程序將退出豁生,GDB 將顯示以下消息判导。

<pre class="no-pretty-print" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: "Roboto Mono", monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">Program terminated with signal SIGTRAP, Trace/breakpoint trap.
The program no longer exists.</pre>

ndk-stack

ndk-stack 工具讓您可以在堆疊追蹤出現在 adb logcat 的輸出中時過濾它們。 它還可以從源代碼將共享庫中的任意地址替換為對應的 <source-file>:<line-number> 值沛硅,從而更容易找出問題所在眼刃。

例如,它可將下面的內容:

<pre class="prettyprint" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: &quot;Roboto Mono&quot;, monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">I/DEBUG (  31):  ***  ***  ***  ***  ***  ***  ***  ***  ***  ***  ***  ***  ***  ***  ***  *** I/DEBUG (  31):  Build fingerprint:  'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys' I/DEBUG (  31): pid:  351, tid:  351 %gt;%gt;%gt;  /data/local/ndk-tests/crasher <<< I/DEBUG (  31): signal 11  (SIGSEGV), fault addr 0d9f00d8 I/DEBUG (  31): r0 0000af88 r1 0000a008 r2 baadf00d  r3 0d9f00d8 I/DEBUG (  31): r4 00000004 r5 0000a008 r6 0000af88 r7 00013c44 I/DEBUG (  31): r8 00000000 r9 00000000 10  00000000 fp 00000000 I/DEBUG (  31): ip 0000959c sp be956cc8  lr 00008403 pc 0000841e cpsr 60000030 I/DEBUG (  31): #00  pc 0000841e  /data/local/ndk-tests/crasher I/DEBUG (  31): #01  pc 000083fe  /data/local/ndk-tests/crasher I/DEBUG (  31): #02  pc 000083f6  /data/local/ndk-tests/crasher I/DEBUG (  31): #03  pc 000191ac  /system/lib/libc.so I/DEBUG (  31): #04  pc 000083ea  /data/local/ndk-tests/crasher I/DEBUG (  31): #05  pc 00008458  /data/local/ndk-tests/crasher I/DEBUG (  31): #06  pc 0000d362  /system/lib/libc.so I/DEBUG (  31):</pre>

轉換為更容易閱讀的輸出:

<pre class="prettyprint" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: &quot;Roboto Mono&quot;, monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">**********  Crash  dump:  **********  Build fingerprint:  'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys' pid:  351, tid:  351 >>>  /data/local/ndk-tests/crasher <<< signal 11  (SIGSEGV), fault addr 0d9f00d8  Stack frame #00  pc 0000841e  /data/local/ndk-tests/crasher : Routine zoo in /tmp/foo/crasher/jni/zoo.c:13  Stack frame #01  pc 000083fe  /data/local/ndk-tests/crasher : Routine bar in /tmp/foo/crasher/jni/bar.c:5  Stack frame #02  pc 000083f6  /data/local/ndk-tests/crasher : Routine my_comparison in /tmp/foo/crasher/jni/foo.c:9  Stack frame #03  pc 000191ac  /system/lib/libc.so  Stack frame #04  pc 000083ea  /data/local/ndk-tests/crasher : Routine foo in /tmp/foo/crasher/jni/foo.c:14  Stack frame #05  pc 00008458  /data/local/ndk-tests/crasher : Routine main in /tmp/foo/crasher/jni/main.c:19  Stack frame #06  pc 0000d362  /system/lib/libc.so</pre>

用法

若要使用 ndk-stack摇肌,首先擂红,您需要一個包含應用共享庫的符號版本的目錄。 如果您使用 NDK 構建系統(tǒng) (ndk-build)围小,則這些共享庫文件位于 $PROJECT_PATH/obj/local/<abi>下昵骤,其中 <abi> 表示您的設備的 ABI。 默認情況下肯适,系統(tǒng)使用 armeabi ABI变秦。

可通過兩種方式使用此工具。您可以將 logcat 文本作為直接輸入饋送到程序框舔。例如:

<pre class="no-pretty-print" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: "Roboto Mono", monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">adb logcat | NDK/ndk-stack -symPROJECT_PATH/obj/local/armeabi
</pre>

您也可以使用 -dump 選項將 logcat 指定為輸入文件蹦玫。例如:

<pre class="no-pretty-print" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: "Roboto Mono", monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">adb logcat > /tmp/foo.txt
NDK/ndk-stack -symPROJECT_PATH/obj/local/armeabi -dump foo.txt
</pre>

該工具在開始解析 logcat 輸出時將查找第一行星號。例如:

<pre class="no-pretty-print" style="box-sizing: inherit; background: rgb(247, 247, 247); color: rgb(55, 71, 79); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: 14px; line-height: 20px; font-family: "Roboto Mono", monospace; padding: 8px; margin: 16px 0px; overflow-x: auto; position: relative;">*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
</pre>

注:在復制/粘貼追蹤時刘绣,請別忘了此行樱溉,否則 ndk-stack 無法正常工作。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末纬凤,一起剝皮案震驚了整個濱河市福贞,隨后出現的幾起案子,更是在濱河造成了極大的恐慌停士,老刑警劉巖挖帘,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件完丽,死亡現場離奇詭異,居然都是意外死亡拇舀,警方通過查閱死者的電腦和手機逻族,發(fā)現死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來你稚,“玉大人,你說我怎么就攤上這事朱躺〉罄担” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵长搀,是天一觀的道長宇弛。 經常有香客問我,道長源请,這世上最難降的妖魔是什么枪芒? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮谁尸,結果婚禮上舅踪,老公的妹妹穿的比我還像新娘。我一直安慰自己良蛮,他們只是感情好抽碌,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著决瞳,像睡著了一般货徙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上皮胡,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天痴颊,我揣著相機與錄音,去河邊找鬼屡贺。 笑死蠢棱,一個胖子當著我的面吹牛,可吹牛的內容都是我干的甩栈。 我是一名探鬼主播裳扯,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谤职!你這毒婦竟也來了饰豺?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤允蜈,失蹤者是張志新(化名)和其女友劉穎冤吨,沒想到半個月后蒿柳,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡漩蟆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年垒探,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怠李。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡圾叼,死狀恐怖,靈堂內的尸體忽然破棺而出捺癞,到底是詐尸還是另有隱情夷蚊,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布髓介,位于F島的核電站惕鼓,受9級特大地震影響,放射性物質發(fā)生泄漏唐础。R本人自食惡果不足惜箱歧,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望一膨。 院中可真熱鬧呀邢,春花似錦、人聲如沸豹绪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽森篷。三九已至输钩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仲智,已是汗流浹背买乃。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钓辆,地道東北人剪验。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像前联,于是被迫代替她去往敵國和親功戚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內容