2015-07-12 77 views
2

我對當前遇到的一個錯誤感到有點困惑,它試圖用C和C++結合JNI和Java來實現一些邏輯。爲什麼從JNI代碼(64位)調用strlen會導致SIGSEGV?

我把它解釋成一個簡單的例子,它每次在Linux上編譯64位時導致崩潰。當使用32位時,它工作正常。 :S

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include <errno.h> 
#include <fcntl.h> 
#include <string.h> 

char * strlenTest() 
{ 
    int size = 100; 
    char * string = (char *) malloc(size * sizeof(char)); 
    int i; 
    for (i = 0; i < 50; i++) 
    { 
     string[i] = 'a'; 
    } 
    string[50] = '\0'; 
    printf("string = '%s'\n", string); 
    int length = strlen(string); 
    printf("string length = %d\n", length); 
    return string; 
} 

這崩潰調用方法:

JNIEXPORT jstring JNICALL Java_foo(JNIEnv *env, 
     jobject thiz, jstring dexPath) { 
    printf("calling test()\n"); 
    char * test = strlenTest(); 
    printf("calling strlen in jni\n"); 
    int testLength = strlen(test); 
    printf("length:%d\n", testLength); 
    } 

輸出: 64位:

calling test() 
string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 
string length = 50 
calling strlen in jni 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# SIGSEGV (0xb) at pc=0x00007f63cbefb6fa, pid=9563, tid=140066607630080 
# 
# JRE version: OpenJDK Runtime Environment (7.0_79-b14) (build 1.7.0_79-b14) 
# Java VM: OpenJDK 64-Bit Server VM (24.79-b02 mixed mode linux-amd64 compressed oops) 
# Derivative: IcedTea 2.5.5 
# Distribution: Ubuntu Vivid Vervet (development branch), package 7u79-2.5.5-0ubuntu1 
# Problematic frame: 
# C [libc.so.6+0x8b6fa] strlen+0x2a 

32位:

calling test() 
string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 
string length = 50 
calling strlen in jni 
length:50 

生成文件:

MARCH=-m64 

CXX  = g++ 
CXXFLAGS = -ansi -g -O0 $(MARCH) -fPIC -I../.. -I/usr/lib/jvm/java-7-openjdk-amd64/include -I/usr/include -Dunix -Wformat=0 
CC  = gcc 
CCFLAGS = -g -O0 -fPIC $(MARCH) -I../.. -I/usr/lib/jvm/java-7-openjdk-amd64/include -I/usr/include -Dunix -Wformat=0 
OBJS  = bugtest.o dexFileParser.o miniunz.o unzip.o ioapi.o 

libname.so : $(OBJS) 
    $(CXX) -o [email protected] $(OBJS) -lz $(MARCH) -shared 

%.o : %.cpp 
    $(CXX) -c $(CXXFLAGS) $< 

%.o : %.c 
    $(CC) -c $(CCFLAGS) $< 

clean: 
    rm *.o 

奇怪的是,在方法本身strlen作品,但是當char *返回到JNI C函數,它在某種程度上崩潰,只有64位。

我真的不明白是怎麼回事。有人可以指出錯誤嗎?

+1

請你可以提供你的構建選項(gcc) - 你有沒有添加-fPIC。我似乎記得這可能會修復庫調用 - 如果它仍然在使用的最新版本。 – Neil

+0

@Neil我添加了相關的Makefile。 – Peterdk

+0

@Peterik,我參加了賭博併發布了一個答案,但是現在我注意到您已經包含了-fPIC(在看到makefile之後)。請至少從ubuntun論壇回顧帖子,讓我們希望這可能會有所幫助! – Neil

回答

0

原來,這個問題是缺少.h文件,宣佈的功能。 編譯器也已經表明,我忽略了一個警告:

initialization makes pointer from integer without a cast

所以,當我加了.h文件正確申報的char * strlenTest();功能,它的工作!

+0

這很酷,有時它是簡單的讓你! – Neil

0

我要在這裏賭一把,並提出以下...

這是從http://ubuntuforums.org/showthread.php?t=1942105拍攝(谷歌是偉大的!)

的問題是使用下面的命令行中發現 -

gcc -c -I/usr/lib/jvm/java-6-openjdk/include -I/usr/lib/jvm/java-6-openjdk/include/linux HelloWorld.c -o libHelloWorld.so 

嘗試64位時的問題是,32位工作得很好 -

答案,其報道工作是... ...

gcc -c -fPIC -I/usr/lib/jvm/java-6-openjdk/include -I/usr/lib/jvm/java-6-openjdk/include/linux HelloWorld.c 

gcc -shared -o libHelloWorld.so HelloWorld.o 

運行的例子 -

LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} java HelloWorld 

請仔細閱讀全文後,我希望這將幫助你解決問題。

+0

我沒有包含/ linux目錄,不幸的是沒有解決它。我已經實施的所有其他選項。太糟糕了,但謝謝你的嘗試! – Peterdk

相關問題