我写了得到一个文件名和一些参数和mmapping(MMAP),它的内存读取文件一个简单的Android原生功能。
由于它的MMAP,我并不真的需要调用读取(),所以我刚才的memcpy()从MMAP地址()返回。
但是,在某处,我得到一个SIGSEGV可能是因为我想访问我不允许的内存。但我不明白为什么,我已经问过的所有文件的存储器映射!
我附上我的code,我得到了错误:
修改
我固定unterminating循环,但仍然得到SIGSEGV 25001984字节被读取后。 该函数可以使用这些参数: jn_bytes =亿 jbuffer_size = 8192 jshared = jpopulate = jadvice = 0
无效Java_com_def_benchmark_Benchmark_testMma $ P $垫(JNIEnv的* ENV,jobject javaThis, 的jstring jfile_name,无符号整型jn_bytes,无符号整型jbuffer_size,jboolean jshared,jboolean jpopulate,jint jadvice){ 为const char * FILE_NAME = ENV-> GetStringUTFChars(jfile_name,0); / * ***开始计*** * / INT FD =打开(FILE_NAME,O_RDONLY); //获取文件的大小 为size_t长度= lseek的(FD,0L,SEEK_END); 使用lseek(FD,0L,SEEK_SET); 长度=长度GT; jn_bytes jn_bytes:长度? // 2人MMAP:因为Linux 2.6.23 MAP_POPULATE只支持民营映射 INT标志= 0; 如果(jshared)标志| = MAP_SHARED;其他标志| = MAP_PRIVATE; 如果(jpopulate)标志| = MAP_POPULATE; // INT标志= MAP_PRIVATE; INT *地址= reinter pret_cast<为int *>(MMAP(NULL,长度,PROT_READ,旗帜,FD,0)); 如果(地址== MAP_FAILED){ __android_log_write(ANDROID_LOG_ERROR,NDK_FOO_TAG,字符串错误(错误)); 返回; } INT * initaddr =地址; 如果(jadvice大于0) 的madvise(地址,长度,jadvice == 1(MADV_SEQUENTIAL | MADV_WILLNEED):( MADV_DONTNEED?)); 关闭(FD); 字符缓冲区[jbuffer_size] 无效* RET_VAL =缓冲区; INT read_length =长度; 而(RET_VAL ==缓冲|| read_length< jbuffer_size){ / *****抵达SIGSEGV SOMWHERE在这里的WHILE ************ / RET_VAL =的memcpy(缓冲区,地址,jbuffer_size); 地址+ = jbuffer_size; read_length - = jbuffer_size; } 在munmap(initaddr,长度); / *停止计数* / ENV-> ReleaseStringUTFChars(jfile_name,FILE_NAME); }和错误日志:
15736 ^做起来难 (GDB) 15737信息信号SIGSEGV &功放;信息信号SIGSEGV \ N 〜信号停止\ t打印\ tPass到程序\ tDescription \ N 〜SIGSEGV是\ tYes \ tYes \ t \ tSegmentation故障\ N 15737 ^做 (GDB) 15738-Stack的列表参数0 0 0 15738 ^做过,堆叠的args = [帧= {级=0,ARGS = []}] (GDB) 15739-Stack的名单,当地人0 15739 ^做,当地人= [] (GDB)解决方案
有一个很大的问题就在这里:
地址+ = jbuffer_size;您正在颠簸地址按的sizeof(int)的* jbuffer_size 字节,而你只是想在加一 jbuffer_size 字节。
我的猜测是的sizeof(int)的 4在系统上,因此你在崩溃周围的方式25%通过你的循环,因为你递增地址以4倍的太多每次迭代的一个因素。
I wrote a simple Android native function that get a filename and some more arguments and read the file by mmapping (mmap) it's memory.
Because it's mmap, I don't really need to call "read()" so I just memcpy() from the address returned from the mmap().
But, somewhere I'm getting a SIGSEGV probably because I'm trying to access a memory which I not permitted. But I don't understand why, I already asked all file's memory to be mapped!
I'm attaching my code and the error I got:
EDIT
I fixed the unterminating loop, but still getting SIGSEGV after 25001984 bytes have been read. The function works on those arguments: jn_bytes = 100,000,000 jbuffer_size = 8192 jshared=jpopulate=jadvice=0
void Java_com_def_benchmark_Benchmark_testMmapRead(JNIEnv* env, jobject javaThis, jstring jfile_name, unsigned int jn_bytes, unsigned int jbuffer_size, jboolean jshared, jboolean jpopulate, jint jadvice) { const char *file_name = env->GetStringUTFChars(jfile_name, 0); /* *** start count *** */ int fd = open(file_name, O_RDONLY); //get the size of the file size_t length = lseek(fd, 0L, SEEK_END); lseek(fd, 0L, SEEK_SET); length = length>jn_bytes?jn_bytes:length; // man 2 mmap: MAP_POPULATE is only supported for private mappings since Linux 2.6.23 int flags = 0; if (jshared) flags |= MAP_SHARED; else flags |= MAP_PRIVATE; if(jpopulate) flags |= MAP_POPULATE; //int flags = MAP_PRIVATE; int * addr = reinterpret_cast<int *>(mmap(NULL, length , PROT_READ, flags , fd, 0)); if (addr == MAP_FAILED) { __android_log_write(ANDROID_LOG_ERROR, "NDK_FOO_TAG", strerror(errno)); return; } int * initaddr = addr; if(jadvice > 0) madvise(addr,length,jadvice==1?(MADV_SEQUENTIAL|MADV_WILLNEED):(MADV_DONTNEED)); close(fd); char buffer[jbuffer_size]; void *ret_val = buffer; int read_length = length; while(ret_val == buffer || read_length<jbuffer_size) { /*****GETTING SIGSEGV SOMWHERE HERE IN THE WHILE************/ ret_val = memcpy(buffer, addr,jbuffer_size); addr+=jbuffer_size; read_length -= jbuffer_size; } munmap(initaddr,length); /* stop count */ env->ReleaseStringUTFChars(jfile_name, file_name); }and the error log:
15736^done (gdb) 15737 info signal SIGSEGV &"info signal SIGSEGV\n" ~"Signal Stop\tPrint\tPass to program\tDescription\n" ~"SIGSEGV Yes\tYes\tYes\t\tSegmentation fault\n" 15737^done (gdb) 15738-stack-list-arguments 0 0 0 15738^done,stack-args=[frame={level="0",args=[]}] (gdb) 15739-stack-list-locals 0 15739^done,locals=[] (gdb)解决方案
There is a big problem here:
addr+=jbuffer_size;You're bumping addr by sizeof(int) * jbuffer_size bytes whereas you just want to increment it by jbuffer_size bytes.
My guess is sizeof(int) is 4 on your system, hence you crash at around 25% of the way through your loop, because you're incrementing addr by a factor of 4x too much on each iteration.
更多推荐
获取分段错误SIGSEGV中的memcpy MMAP后
发布评论