12

The following code causes a segmentation fault after printing the string:

#include <iostream>
using namespace std;

int main()
{
    cout << "ndktest" << endl;
    return 0;
}
  • If I change cout to printf, it doesn't crash.
  • If I call cout in a different function other than main, and that function is never accessed, it still crashes.
  • It crashes on Froyo, but not ICS.

For reference, here's my Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ndktest
LOCAL_SRC_FILES := main.cpp

include $(BUILD_EXECUTABLE)

and Application.mk:

APP_STL := stlport_static

Here's the crash from 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)

Running this through the stack trace tool didn't yield any symbolic information.

Update:

The pc value in the crash dump (0001972c in /system/lib/libc.so) is in an exit routine, which is consistent with crashing after the string is printed:

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
Ravi
  • 3,718
  • 7
  • 39
  • 57
  • Have you not looked into adding `LOCAL_LDLIBS += -ldl` and `LOCAL_SHARED_LIBRARIES += libdl` into your Android.mk? The reason I say `dl` specifically, is the dynamic linking portion to link in the shared library for the stlport. – t0mm13b Jul 13 '12 at 21:04
  • @t0mm13b: I tried that, but still get "CANNOT LINK EXECUTABLE" when I run the program. How would I load libstlport_shared.so in main()? – Ravi Jul 13 '12 at 23:00
  • http://stackoverflow.com/questions/7339229/android-std-and-stl-support, http://sseyod.blogspot.ie/2009/08/android-jni-ndk-and-stl-support.html, http://stackoverflow.com/questions/1650963/ustl-or-stlport-for-android <- the last linky could be the answer... check it out :) – t0mm13b Jul 13 '12 at 23:58
  • Just use `gnustl_static` instead of `stlport_static` or whatever. That one is known to work correctly. – Samuel Audet Jul 14 '12 at 02:49
  • Same result with gnustl_static. – Ravi Jul 14 '12 at 04:56

1 Answers1

5

This is probably due to the fact that you use stlport_static instead of stlport_shared.

In the NDK docs (CPLUSPLUS-SUPPORT.html included in the package), this behaviour is described. This unpredicted behaviour derives from the fact that if the application links against two (or more) shared libraries, and both link against stlport_static, some symbols may be duplicated, leading to incorrect behaviour.

Sdra
  • 2,297
  • 17
  • 30
  • I don't have any shared libraries in my project. In my makefile above, I'm just building one executable that statically links STL. Is there a reason I would need to switch to a shared version of STL? – Ravi Jul 09 '12 at 16:47
  • I'm not clear on how to use STL as a shared library at the NDK layer. If I use stlport_shared, the documentation says to load the library in a static Java initializer. Does that mean I need to build this as an apk? I'm trying to preserve this project as a pure NDK executable because it has a command line interface, and I'd like to make it part of /system/xbin. – Ravi Jul 10 '12 at 13:45
  • @Ravi: it should make not difference if you link it statically or dynamically. The only thing that changes is that when linking dynamically, the stlport library has to be in the library path. If it is not then you can add the path where the stlport library is to the LD_LIBRARY_PATH environment library. But I guess there should be no need. – Sdra Jul 12 '12 at 09:56
  • @Sdra: I changed Application.mk to APP_STL := stlport_shared. I'm able to compile and link, but when I execute I get a message saying "CANNOT LINK EXECUTABLE". Setting LD_LIBRARY_PATH didn't help. Normally with dynamic linking, I would use dlopen and dlsym to access functions, but I'm not sure how that would work with STL. The NDK documentation says dynamic linking of STL requires Java code to load the STL library before using it. At that point, I would end up with an apk, which I can't use since my app requires a native command line interface. – Ravi Jul 12 '12 at 17:19
  • Hi Ravi, I don't think you need dlopen or dlsym, nor you need any Java code, that would be just if your native code is loaded by a java virtual machine and used through JNI. As a suggestion, don't think here in terms of Android, but in terms of Linux. Does the linker says something more than "CANNOT LINK EXECUTABLE"? Btw, LD_LIBRARY_PATH is needed at run time, here you need to set the library path at compile time with "-L" (make sure there's no default library path containing other stlport libs that could conflict). – Sdra Jul 16 '12 at 08:52
  • @Sdra: The exact error message is "link_image[2046]: failed to link ./ndktest CANNOT LINK EXECUTABLE". I got rid of Application.mk, and manually defined LOCAL_LDFLAGS (with -L path), LOCAL_LDLIBS, and LOCAL_C_INCLUDES to point to the STL shared library and headers. It compiled and linked, but when I execute I still get the same error message. – Ravi Jul 17 '12 at 01:18
  • For what it's worth, I wrapped the NDK code inside an APK, and it didn't seg fault. I was still using stlport_static. This isn't a viable solution (for reasons discussed above), but I just wanted to see if stlport_static would work. – Ravi Jul 17 '12 at 01:48
  • @Ravi: I think link_image[2046] comes from dlopen. In that case setting LD_LIBRARY_PATH doesn't help since you specify the full path of the library as an argument of dlopen. You can check if there is any library dependency missing with "arm-eabi-objdump -p libstlport_shared.so" or something like that. the objdump should be provided by the NDK. You have to make sure that all the dependencies are correctly installed. BTW, if it's possible you should avoid explicitly linking a library with dlopen (especially stl library) and let the compiler and runtime environment link for you. – Sdra Jul 17 '12 at 09:57
  • I tried the NDK objdump command you mentioned, and it lists libc and libm as dependencies. According to the NDK docs, these are automatically included/installed. I verified they're both in /system/lib on my target. I'm not calling dlopen in my code. I haven't changed anything from the code in my post above. How does dynamic linking work when there's no explicit dlopen - is there some glue code that does finds the so and makes the functions available? – Ravi Jul 17 '12 at 16:53
  • Yes. The runtime environment takes care of that. dlopen should be used just in rare conditions. – Sdra Jul 18 '12 at 08:57