在C中使用mmap读取二进制文件时出现段错误 [英] Segfault while using mmap in C for reading binary files

查看:508
本文介绍了在C中使用mmap读取二进制文件时出现段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在C中使用mmap只是为了查看它的工作原理.目前,我正在尝试使用mmap逐字节读取二进制文件.我的代码是这样的:

I am trying to use mmap in C just to see how it exactly works. Currently I am try to read a binary file byte by byte using mmap. My code is like this:

#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>    

int main(int argc, char *argv[]) {
    int fd;
    char *data;

    for ( int i = 1; i<argc; i++)
    {

        if(strcmp(argv[i],"-i")==0)
            fd = open(argv[i+1],O_RDONLY);
    }

    data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000);
    int i = 0;
    notation = data [i];
    // ......

}

当我尝试使用符号= data [0]并遇到segfault时,就会发生我的问题.我确定二进制文件中的第一个字节也是一个字符.我的for循环检查在编译时是否有-i标志,是否有下一个参数应该是文件名.

My problem occurs when I try notation = data[0] and I get a segfault . I am sure that the first byte in the binary file is a character as well. My for loop checks if there is an -i flag while compiling , if there is the next argument should be the file name.

推荐答案

mmap似乎失败,因为偏移量不是页面大小的倍数.您可以使用perror进行测试,然后查看问题是否为无效参数.如果您写:

It appears that mmap fails because the offset is not a multiple of page size. You can test this with perror and see that the problem is an invalid argument. If you write:

data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000);
perror("Error");

至少在我的OS X上会显示以下错误:

At least on my OS X the following error is printed:

错误:参数无效

将偏移量从8000更改为4096或8192. 6144不需要,因此在该平台上必须是4096的倍数.顺便说一句,

Changing offset from 8000 to 4096 or 8192 works. 6144 doesn't, so it has to be a multiple of 4096 on this platform. Incidentally,

printf("%d\n",getpagesize());

打印4096.您应将偏移量向下舍入到mmap的最接近倍数,并在访问该区域时将余数添加到i.当然,可以从该功能获取特定平台的页面大小.它可能是在您已经声明的unistd.h中定义的.

prints 4096. You should round your offset down to nearest multiple of this for mmap and add the remainder to i when accessing the area. Of course, get the page size for your particular platform from that function. It's probably defined in unistd.h, which you already declared.

这是正确处理偏移并处理可能的错误的方法.它在位置8000处打印字节:

Here's how to handle the offset correctly and deal with possible errors. It prints the byte at position 8000:

int offset = 8000;
int pageoffset = offset % getpagesize();

data = mmap(NULL, 4000 + pageoffset, PROT_READ, MAP_SHARED, fd, offset - pageoffset);
if ( data == MAP_FAILED ) {
    perror ( "mmap" );
    exit ( EXIT_FAILURE );
}
i = 0;
printf("%c\n",data [i + pageoffset]);

这篇关于在C中使用mmap读取二进制文件时出现段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆