获取分段错误SIGSEGV中的memcpy MMAP后

编程入门 行业动态 更新时间:2024-10-19 00:23:27
本文介绍了获取分段错误SIGSEGV中的memcpy MMAP后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我写了得到一个文件名和一些参数和mmapping(MMAP),它的内存读取文件一个简单的Andr​​oid原生功能。

由于它的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 ^做过,堆叠的a​​rgs = [帧= {级=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后

本文发布于:2023-10-09 05:55:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1474892.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:错误   SIGSEGV   MMAP   memcpy

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!