Getting segmentation fault SIGSEGV in memcpy after mmap(在 mmap 之后在 memcpy 中获取分段错误 SIGSEGV)
问题描述
我编写了一个简单的 Android 原生函数,它获取文件名和更多参数,并通过映射 (mmap) 它的内存来读取文件.
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.
因为是mmap,所以我不需要调用read()",所以我只是从mmap()返回的地址中memcpy().
Because it's mmap, I don't really need to call "read()" so I just memcpy() from the address returned from the mmap().
但是,我在某个地方得到了 SIGSEGV,可能是因为我试图访问我不允许的内存.但是我不明白为什么,我已经要求映射所有文件的内存!
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:
编辑
我修复了终止循环,但在读取 25001984 个字节后仍然得到 SIGSEGV.该函数适用于这些参数:jn_bytes = 100,000,000jbuffer_size = 8192jshared=jpopulate=jadvice=0
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);
}
和错误日志:
15736^done
(gdb)
15737 info signal SIGSEGV
&"info signal SIGSEGV
"
~"Signal Stop Print Pass to program Description
"
~"SIGSEGV Yes Yes Yes Segmentation fault
"
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)
推荐答案
这里有个大问题:
addr+=jbuffer_size;
您将 addr
增加 sizeof(int) * jbuffer_size
字节,而您只想将其增加 jbuffer_size
字节.
You're bumping addr
by sizeof(int) * jbuffer_size
bytes whereas you just want to increment it by jbuffer_size
bytes.
我的猜测是 sizeof(int)
在你的系统上是 4,因此你在循环的大约 25% 处崩溃,因为你正在递增 addr
每次迭代增加 4 倍.
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.
这篇关于在 mmap 之后在 memcpy 中获取分段错误 SIGSEGV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在 mmap 之后在 memcpy 中获取分段错误 SIGSEGV


- 用 Swift 实现 UITextFieldDelegate 2022-01-01
- android 4中的android RadioButton问题 2022-01-01
- 想使用ViewPager,无法识别android.support.*? 2022-01-01
- 在测试浓缩咖啡时,Android设备不会在屏幕上启动活动 2022-01-01
- Android - 我如何找出用户有多少未读电子邮件? 2022-01-01
- MalformedJsonException:在第1行第1列路径中使用JsonReader.setLenient(True)接受格式错误的JSON 2022-01-01
- Android - 拆分 Drawable 2022-01-01
- 如何检查发送到 Android 应用程序的 Firebase 消息的传递状态? 2022-01-01
- Android viewpager检测滑动超出范围 2022-01-01
- 使用自定义动画时在 iOS9 上忽略 edgesForExtendedLayout 2022-01-01