【问题标题】:Linking STL into a standalone Android NDK executable将 STL 链接到独立的 Android NDK 可执行文件
【发布时间】:2012-07-06 21:18:09
【问题描述】:

以下代码在打印字符串后导致分段错误:

#include <iostream>
using namespace std;

int main()
{
    cout << "ndktest" << endl;
    return 0;
}
  • 如果我将 cout 更改为 printf,它不会崩溃。
  • 如果我在除 main 之外的其他函数中调用 cout,那么 函数永远不会被访问,它仍然会崩溃。
  • 它在 Froyo 上崩溃,但不是 ICS。

作为参考,这是我的 Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ndktest
LOCAL_SRC_FILES := main.cpp

include $(BUILD_EXECUTABLE)

和 Application.mk:

APP_STL := stlport_static

这是来自 logcat 的崩溃:

I/DEBUG   (  872): pid: 4234, tid: 4234  >>> /data/ndktest <<<
I/DEBUG   (  872): signal 11 (SIGSEGV), fault addr 00024004
I/DEBUG   (  872):  r0 00033824  r1 00001000  r2 00024005  r3 bea42cfc
I/DEBUG   (  872):  r4 40008090  r5 0000000a  r6 40008000  r7 afd42328
I/DEBUG   (  872):  r8 00000000  r9 00000000  10 00000000  fp 00000000
I/DEBUG   (  872):  ip 40008084  sp bea42ce8  lr afd192dd  pc 00024004  cpsr 60000030
I/DEBUG   (  872):  d0  0000000000000000  d1  0000000000000000
I/DEBUG   (  872):  d2  0000000000000000  d3  0000000000000000
I/DEBUG   (  872):  d4  0000000000000000  d5  0000000000000000
I/DEBUG   (  872):  d6  0000000000000000  d7  0000000000000000
I/DEBUG   (  872):  d8  0000000000000000  d9  0000000000000000
I/DEBUG   (  872):  d10 0000000000000000  d11 0000000000000000
I/DEBUG   (  872):  d12 0000000000000000  d13 0000000000000000
I/DEBUG   (  872):  d14 0000000000000000  d15 0000000000000000
I/DEBUG   (  872):  scr 00000000
I/DEBUG   (  872): 
I/DEBUG   (  872):          #00  pc 00024004  
I/DEBUG   (  872):          #01  pc 000192da  /system/lib/libc.so
I/DEBUG   (  872):          #02  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #03  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #04  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #05  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #06  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #07  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #08  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #09  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #10  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #11  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #12  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #13  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #14  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #15  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #16  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #17  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #18  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #19  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #20  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #21  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #22  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #23  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #24  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #25  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #26  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #27  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #28  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #29  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #30  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872):          #31  pc 0001972c  /system/lib/libc.so
I/DEBUG   (  872): 
I/DEBUG   (  872): code around pc:
I/DEBUG   (  872): 00023fe4 ffffffff ffffffff ffffffff ffffffff 
I/DEBUG   (  872): 00023ff4 ffffffff ffffffff ffffffff ffffffff 
I/DEBUG   (  872): 00024004 ffffffff ffffffff ffffffff ffffffff 
I/DEBUG   (  872): 00024014 ffffffff ffffffff ffffffff ffffffff 
I/DEBUG   (  872): 00024024 ffffffff ffffffff ffffffff ffffffff 
I/DEBUG   (  872): 
I/DEBUG   (  872): code around lr:
I/DEBUG   (  872): afd192bc f8cde018 f7f4e00c b930ec56 0c0cf844 
I/DEBUG   (  872): afd192cc 46302201 f7f49900 9803ec4e 47909a05 
I/DEBUG   (  872): afd192dc f1153c0c d5d735ff 2e006836 463cd1ce 
I/DEBUG   (  872): afd192ec b9b99901 c03cf8df 300cf857 f8471e58 
I/DEBUG   (  872): afd192fc b978000c 587a490c e0046810 68059900 
I/DEBUG   (  872): 
I/DEBUG   (  872): stack:
I/DEBUG   (  872):     bea42ca8  b000c9b8  
I/DEBUG   (  872):     bea42cac  00000014  
I/DEBUG   (  872):     bea42cb0  b00093e0  /system/bin/linker
I/DEBUG   (  872):     bea42cb4  b001e9b8  
I/DEBUG   (  872):     bea42cb8  b000c9b8  
I/DEBUG   (  872):     bea42cbc  b0001c78  /system/bin/linker
I/DEBUG   (  872):     bea42cc0  b001e724  
I/DEBUG   (  872):     bea42cc4  00000005  
I/DEBUG   (  872):     bea42cc8  b000c9b8  
I/DEBUG   (  872):     bea42ccc  b0001de3  /system/bin/linker
I/DEBUG   (  872):     bea42cd0  b000c9b8  
I/DEBUG   (  872):     bea42cd4  b0002c77  /system/bin/linker
I/DEBUG   (  872):     bea42cd8  00000000  
I/DEBUG   (  872):     bea42cdc  b001ffe8  
I/DEBUG   (  872):     bea42ce0  df002777  
I/DEBUG   (  872):     bea42ce4  e3a070ad  
I/DEBUG   (  872): #01 bea42ce8  00001000  
I/DEBUG   (  872):     bea42cec  00000000  
I/DEBUG   (  872):     bea42cf0  bea42cfc  
I/DEBUG   (  872):     bea42cf4  00033824  
I/DEBUG   (  872):     bea42cf8  00000000  
I/DEBUG   (  872):     bea42cfc  00024005  
I/DEBUG   (  872):     bea42d00  00033824  
I/DEBUG   (  872):     bea42d04  00000000  
I/DEBUG   (  872):     bea42d08  00000000  
I/DEBUG   (  872):     bea42d0c  00000000  
I/DEBUG   (  872):     bea42d10  b000c9b8  
I/DEBUG   (  872):     bea42d14  00000000  
I/DEBUG   (  872):     bea42d18  00000000  
I/DEBUG   (  872):     bea42d1c  afd19731  /system/lib/libc.so
I/BootReceiver(  946): Copying /data/tombstones/tombstone_09 to DropBox (SYSTEM_TOMBSTONE)

通过堆栈跟踪工具运行它并没有产生任何符号信息。

更新:

崩溃转储中的 pc 值(/system/lib/libc.so 中的 0001972c)在退出例程中,与打印字符串后崩溃一致:

00019728 <exit>:
   19728:   4604        mov r4, r0
   1972a:   2000        movs    r0, #0
   1972c:   f7ff fd8c   bl  19248 <__cxa_finalize>
   19730:   4620        mov r0, r4
   19732:   f7f3 ee96   blx d460 <_exit>
   19736:   bf00        nop

【问题讨论】:

标签: android c++ stl android-ndk


【解决方案1】:

这可能是因为您使用 stlport_static 而不是 stlport_shared。

在 NDK 文档(包中包含 CPLUSPLUS-SUPPORT.html)中,描述了这种行为。这种不可预知的行为源于这样一个事实:如果应用程序链接到两个(或更多)共享库,并且都链接到 stlport_static,则某些符号可能会重复,从而导致不正确的行为。

【讨论】:

  • 我的项目中没有任何共享库。在上面的 makefile 中,我只是构建了一个静态链接 STL 的可执行文件。我是否有理由需要切换到 STL 的共享版本?
  • 我不清楚如何在 NDK 层使用 STL 作为共享库。如果我使用 stlport_shared,文档说明将库加载到静态 Java 初始化程序中。这是否意味着我需要将其构建为 apk?我正在尝试将此项目保留为纯 NDK 可执行文件,因为它具有命令行界面,并且我想让它成为 /system/xbin 的一部分。
  • @Ravi:静态或动态链接应该没什么区别。唯一改变的是动态链接时,stlport 库必须在库路径中。如果不是,那么您可以将 stlport 库所在的路径添加到 LD_LIBRARY_PATH 环境库中。但我想应该没有必要。
  • @Sdra:我将 Application.mk 更改为 APP_STL := stlport_shared。我能够编译和链接,但是当我执行时,我收到一条消息说“无法链接执行”。设置 LD_LIBRARY_PATH 没有帮助。通常使用动态链接,我会使用 dlopen 和 dlsym 来访问函数,但我不确定这将如何与 STL 一起使用。 NDK 文档说 STL 的动态链接需要 Java 代码在使用之前加载 STL 库。那时,我最终会得到一个 apk,但我无法使用它,因为我的应用程序需要本机命令行界面。
  • 您好 Ravi,我认为您不需要 dlopen 或 dlsym,也不需要任何 Java 代码,只要您的本机代码由 Java 虚拟机加载并通过 JNI 使用即可。作为一个建议,不要在这里考虑 Android,而是考虑 Linux。链接器是否比“CANNOT LINK EXECUTABLE”更能说明问题?顺便说一句,运行时需要 LD_LIBRARY_PATH,这里您需要在编译时使用“-L”设置库路径(确保没有包含可能冲突的其他 stlport 库的默认库路径)。
猜你喜欢
  • 1970-01-01
  • 2011-06-21
  • 2015-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-17
  • 1970-01-01
相关资源
最近更新 更多