C++ Android NDK:调用System.loadLibrary会导致SIGSEGV代码=1
我有一个巨大的C/C++库,我正试图通过JNI将其用于Android项目。它由几个最初为MFC编写的类组成,我们将它们移植到Android环境中执行 库构建良好(至少根据ndk构建)。该库的大小为56MB 调用System.loadLibrary时,应用程序将终止,并记录以下内容: 0x00000004(代码=1)处的致命信号11(SIGSEGV),线程16123 我在我的库上执行了一个objdump,在0004没有任何内容。以下是转储的前几行:C++ Android NDK:调用System.loadLibrary会导致SIGSEGV代码=1,c++,android-ndk,java-native-interface,segmentation-fault,loadlibrary,C++,Android Ndk,Java Native Interface,Segmentation Fault,Loadlibrary,我有一个巨大的C/C++库,我正试图通过JNI将其用于Android项目。它由几个最初为MFC编写的类组成,我们将它们移植到Android环境中执行 库构建良好(至少根据ndk构建)。该库的大小为56MB 调用System.loadLibrary时,应用程序将终止,并记录以下内容: 0x00000004(代码=1)处的致命信号11(SIGSEGV),线程16123 我在我的库上执行了一个objdump,在0004没有任何内容。以下是转储的前几行: DYNAMIC SYMBOL TABLE: 00
DYNAMIC SYMBOL TABLE:
00000000 DF *UND* 00000000 __cxa_finalize
002fe600 g D .bss 00000000 __dso_handle
002f1e9c g D .init_array 00000000 __INIT_ARRAY__
002f20a4 g D .fini_array 00000000 __FINI_ARRAY__
0011dc58 g DF .text 000000ec WideToJava
00000000 DF *UND* 00000000 __android_log_print
0021f460 g DF .text 00000030 wcslen
00000000 DF *UND* 00000000 malloc
00000000 DF *UND* 00000000 free
0011dd44 g DF .text 000000e4 WideToJava2
0011de28 g DF .text 0000004e JavaToWSZ
0027443c g DF .text 0000001c _Znaj
0011dec4 w DF .text 00000018
然后,我执行了readelf以查看是否还有其他库需要加载,如下所示:
Dynamic section at offset 0x2d99e0 contains 28 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0x2fe464
0x00000002 (PLTRELSZ) 776 (bytes)
0x00000017 (JMPREL) 0x11d4a0
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x107770
0x00000012 (RELSZ) 89392 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 11169
0x00000006 (SYMTAB) 0x128
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x31cd8
0x0000000a (STRSZ) 791389 (bytes)
0x00000004 (HASH) 0xf3038
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libandroid.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x0000000e (SONAME) Library soname: [libCSEntry.so]
0x00000019 (INIT_ARRAY) 0x2f1e9c
0x0000001b (INIT_ARRAYSZ) 520 (bytes)
0x0000001a (FINI_ARRAY) 0x2f20a4
0x0000001c (FINI_ARRAYSZ) 12 (bytes)
0x00000016 (TEXTREL) 0x0
0x00000010 (SYMBOLIC) 0x0
0x0000001e (FLAGS) SYMBOLIC TEXTREL
0x00000000 (NULL) 0x0
然后在调用loadLibrary之前添加了这些库:
public class ApplicationInterface
{
static
{
System.loadLibrary("log");
System.loadLibrary("android");
System.loadLibrary("stdc++");
System.loadLibrary("m");
System.loadLibrary("c");
System.loadLibrary("dl");
// when i call load library it blows up
System.loadLibrary("CSEntry");
}
// code
}
奇怪的是,有一个特定的类破坏了这段代码。当我注释掉这个类的构造器时,这个库加载得很好。我已经使用objdump验证了结果库中是否存在构造函数。然后我继续在构造函数中注释掉代码,它也失败了。下面是C++中令人不快的代码:
// Code
m_pPifFile = new CNPifFile(sPifFilePath);
m_pPifFile->SetAppType(ENTRY_TYPE);
m_pPifFile->SetAppFName(sApplicationFilename);
m_pPifFile->SetBinaryLoad(true);
// load the PIF file
if(m_pPifFile->LoadPifFile())
{
// PIF file loaded create a new Run App
// the offending line
m_pRunAplEntry = new CRunAplEntry(m_pPifFile);
// Code
runapletry.h
class AFX_EXT_CLASS CRunAplEntry : public CRunApl
{
public:
CRunAplEntry(CNPifFile* pPifFile);
~CRunAplEntry();
// code
};
RunApl.h
class CLASS_DECL_ZBRIDGEO CRunApl : public CObject
{
public:
CRunApl();
virtual ~CRunApl();
// code
};
AFX#U EXT#U CLASS和CLASS#DECL#ZBRIDGEO定义为空空间
我们为Android NDK编写了一个CObject等价物
以下是生成文件:
Application.mk
# set the platform to the latest processor type
APP_ABI := armeabi-v7a
# build for GNU STL
APP_STL := gnustl_static
# turn on exceptions and runtime type info
APP_CPPFLAGS += -fexceptions -frtti
Android.mk
LOCAL_LDLIBS := -llog -landroid $(BOOST_LIBS) -lgnustl_static
LOCAL_LDFLAGS := -L$(BOOST_PATH)/lib/arm
LOCAL_CFLAGS := -D__GLIBC__=1
LOCAL_CFLAGS += -D_GLIBCXX_USE_C99_MATH=1
LOCAL_CFLAGS += -DUNICODE=1
LOCAL_CFLAGS += -D_UNICODE=1
LOCAL_CFLAGS += -DGENERATE_BINARY=1
LOCAL_CFLAGS += -DUSE_BINARY=1
LOCAL_CFLAGS += -DPORTABLE=1
LOCAL_CFLAGS += -fpermissive
LOCAL_CFLAGS += $(CSPROMOBILE_INCLUDE)
LOCAL_STATIC_LIBRARIES := Engine zTbdO zFormO zDictO zToolsO zUtilO zCommonO
我注意到GCC编译器不能很好地处理虚拟函数,我怀疑这可能是问题所在,但我不确定。以下是我的环境的详细信息
NDK:Crystax r75
ABI目标:4.6.3
ADT:v21.0.1-543035
调试设备:Nexus7
任何帮助都将不胜感激
如果您有任何其他信息,请随时询问
谢谢,
将故障地址(00000004)是访问的无效虚拟地址。很可能这是一个空指针取消引用。我猜想静态构造函数正在执行,但正在崩溃。您应该能够从logcat中出现的debuggerd堆栈跟踪中了解更多信息——那里的地址和偏移量应该直接映射到您的代码。谢谢fadden,我感谢您的回复。但是,logcat没有打印任何附加信息。就在那条被炸毁的线路上。为了在执行本机代码时显示整个跟踪,是否需要设置一些特殊的内容?有几种情况下,debuggerd会被绕过。在这些情况下,您需要附加一个调试器(将日志消息和睡眠调用放在loadLibrary()之前,附加gdb),或者使用printf()来找出它实际上在哪里消亡。嗨,Fadden,您说得对。有人让一个静态构造函数对一个静态分配的变量做了一大堆废话。嘘!