2

那么我有这个程序,我得到一个分段错误:11(核心转储)。经过大量检查后,当for循环到达i = 1024并尝试mapfile [i] = 0时,我得到了这个。该程序是关于制作服务器和客户端程序,通过在服务器程序中制作的公共文件中读/写进行通信。这是服务器程序,它打印更改前后的值。我想看看发生了什么,是映射有问题还是*mapfile的内存有问题。谢谢!

#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>

int main()
{
    int ret, i;           
    int *mapfile;           

    system("dd if=/dev/zero of=/tmp/c4 bs=4 count=500");

    ret = open("/tmp/c4", O_RDWR | (mode_t)0600);
    if (ret == -1)
    {
        perror("File");
        return 0;
    }

    mapfile = mmap(NULL, 2000, PROT_READ | PROT_WRITE, MAP_SHARED, ret, 0);

    for (i=1; i<=2000; i++)
    {
        mapfile[i] = 0;
    }

    while(mapfile[0] != 555)
    {
        mapfile = mmap(NULL, 2000, PROT_READ | PROT_WRITE, MAP_SHARED, ret, 0);
        if (mapfile[0] != 0)
        {
            printf("Readed from file /tmp/c4 (before): %d\n", mapfile[0]);
            mapfile[0]=mapfile[0]+5;
            printf("Readed from file /tmp/c4 (after)  : %d\n", mapfile[0]);
            mapfile[0] = 0;
        }
        sleep(1);
    }

    ret = munmap(mapfile, 2000);
    if (ret == -1)
    {
        perror("munmap");
        return 0;
    }

    close(ret);

    return 0;
}
4

2 回答 2

2

You're requesting 2000 bytes from mmap, but treating the returned value as an array of 2000 ints. That can't work, an int is usually 4 or 8 bytes these days. You'll be writing past the end of the reserved memory in your loop.

Change the mmap calls to use 2000*sizeof(int). And while you're at it, give that 2000 constant a name (e.g. const int num_elems = 2000; near the top) and don't repeat the magic constant all over the place. And once that's done change it to 1024 or 2048 so that the resulting size is a multiple of the page size (if you're not sure of your page size, getconf PAGE_SIZE on the command line).

And also change your dd command to create a large-enough file. It is currently creating a 2000 byte file, you'll need to increase that as well.

And validate the return value of mmap - it can fail, and you should detect that.

Finally, don't continuously remap, you're using MAP_SHARED modifications through other shared mappings of the same file and offset will be visible to your process. (Must really be the same file, if the other process also does a dd, that might not work. Only one process should have the responsibility of creating that file.)

If you do want to remap, you must also unmap each time. Otherwise you're leaking mappings.

于 2014-05-09T16:58:14.680 回答
2
mapfile = mmap(NULL, 2000, PROT_READ | PROT_WRITE, MAP_SHARED, ret, 0);

for (i=1; i<=2000; i++)
{
    mapfile[i] = 0;
}

在此代码中,您看到您正在请求 2000 个内存单位。在这种情况下, mmap 采用 size_t 类型,这意味着它正在寻找一个大小,而不是内存的数量。正如@Mat 提到的,您将需要使用 sizeof(int) 运算符才能为 mmap 提供所需的适当大小。

关于此代码应该注意的另一个可能会给您带来问题的问题是,您的循环索引从 i=1 而不是 i=0 开始。从 0 开始索引将确保您从索引 0 - 1999 开始,这对应于您尝试分配的内存。

总的来说,看起来你试图做的是将你的内存值初始化为 0。也许你可以通过一个名为 memset 的内置函数来更容易地做到这一点:

void *memset(void *str, int c, size_t n)

然后你的代码变成:

mapfile = mmap(NULL, 2000*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, ret, 0);
void *returnedPointer = memset(mapfile, 0, 2000*sizeof(int));

memset 的文档可以在这里找到: http ://www.tutorialspoint.com/c_standard_library/c_function_memset.htm

于 2014-05-09T17:11:36.810 回答