Warm tip: This article is reproduced from serverfault.com, please click

c-从共享内存中读取数组时获取SEGFAULT

(c - getting SEGFAULT when reading an array from shared memory)

发布于 2020-12-02 23:50:26

我是使用共享内存的新手,对于第一个文件,实现可以正常工作,但是对于第二个文件,它无法从共享内存中读取一些结构。我认为问题出在我的mmap中,但不太确定到底是什么

第一个文件,效果很好:

  struct Sh_Mem* open_res(int nb_tables)
    {
        size_t mem_size = MEM_SIZE(nb_tables);
        int shm_fd=shm_open(MEM_NAME,O_RDWR|O_CREAT | O_TRUNC, 0600);
        if(shm_fd<0)
            raler("shm_open");
        
        ftruncate(shm_fd,mem_size);
        
        struct Sh_Mem * res=mmap(NULL,mem_size,PROT_READ| PROT_WRITE,MAP_SHARED,shm_fd,0);
        if(res == NULL)
            raler("mmap");
        res->nb_tables=nb_tables;
        res->size = mem_size;
        
        return res;
    }
int main(int argc, char const *argv[])
{

    if (argc < 3)
        raler("Usage : ./restaurant <duree_repas> <capacite_des_tables>");
    
    
    int dinner_time = atoi(argv[1]);
    int nb_tables = argc -2;
    int fermeture=0;
    struct table* tables=malloc(nb_tables*sizeof(struct table));
    
    if (dinner_time < 100 )
        raler("Duree de repas tres courte");

    struct Sh_Mem* res=open_res(nb_tables);
    res->table = malloc(nb_tables*sizeof(struct table));

    for(int i = 2; i < (argc); i++)
    {
        if(atoi(argv[i])>6 || atoi(argv[i])<1 )
        {
            printf("\nERROR : %s\n ",argv[i] ); 
            raler("Max Capacity of Tables is 6 ");
        }
        tables[i-2].size = atoi(argv[i]);
        
    }
    res->table=tables;
    shm_unlink(MEM_NAME);
    return 0;
}

第二个文件给我一个分段错误:

struct Sh_Mem* first_guest(char * nom)
{

    int shm_fd=shm_open(MEM_NAME,O_RDWR, 0600);
    if(shm_fd<0)
        raler("shm_open");
    struct stat stat;
    if(fstat(shm_fd, &stat) < 0) {
        perror("fstat");
        exit(1);
    }
    struct Sh_Mem * guests=mmap(NULL,stat.st_size,PROT_READ| PROT_WRITE,MAP_SHARED,shm_fd,0);
    if(guests == NULL)
        raler("mmap");  
return guests;
}
int main(int argc, char const *argv[])
{
    if (argc != 3)
        raler("Usage : ./convive <nom_du_convive> <nombres_de_personnes_dans_le_groupe/nom_du_premier_convive>");
    
    if(strlen(argv[1])>10)
        raler("Name has to be less or equal to 10 char ");
    
    if(isdigit(argv[1][0]))
        raler("First argument has to start with a character");

    if (isdigit(argv[2][0]))
    {
struct Sh_Mem* res=first_guest((char*)argv[1]);
        for (int i = 0; i < res->nb_tables; i++)
        {
            if(res->table[i].used==1)
            {

                continue;
            }
            if(res->table[i].size == atoi(argv[2]))
                {
                    found =1;

                    res->table[i].name=(char *)argv[1];
                    res->table[i].used =1;
                }
                printf("%s\n",res->table[i].name );
        }

每当我通过res-> tables时,都会发生该错误。我测试了它是否等于null,但它也不是这里的struct:

void raler(char *msg)
{
    perror(msg);
    exit(1);
}
struct table
{
    int id;
    int size;
    char* name;
    int nb_left;
    int used;

};
struct Sh_Mem{

int nb_tables;
size_t size;
struct table* table;
};
#define MEM_NAME "/guest"
#define MEM_SIZE(nb_table) sizeof (struct Sh_Mem) + (nb_table)*sizeof (struct convive)+ (nb_table)*sizeof (struct table)
Questioner
Kaspercold 1
Viewed
0
David Schwartz 2020-12-03 07:58:10
                res->table[i].name=(char *)argv[1];
            }
            printf("%s\n",res->table[i].name );

这是行不通的。你正在将指针放入当前进程的地址空间中,并将其放入共享内存中。这对任何其他过程都没有任何意义。

你可以通过制作name固定长度的数组或分配一些共享内存并name指向它来解决此问题。请小心-每个进程都必须计算指向共享内存的正确本地指针,因为不同的进程可能会将同一共享内存段映射到不同的地址。