首页 > 解决方案 > 从函数调用时 munmap() 不起作用

问题描述

我正在编写一个与共享内存一起使用的函数库。我为关闭共享内存而编写的函数在到达 munmap() 部分时会给我一个段错误,但如果我不使用该函数而只是让代码 munmap() 和 shm_unlink 在最后,它可以工作。我很困惑为什么。代码如下。

void close_table(table_t *tbl, char* name){
  size_t size = sizeof(tbl->table_size);
  printf("table_size: %d\n", tbl->table_size);
  /* when the first part of if else statement runs its fine */
  if(tbl->numP > 1){
    printf("first if statement\n");
    tbl->numP -= 1;
    munmap(tbl, tbl->table_size);
  }
  /* when second part runs gives seg fault */
  else{
    tbl->numP -= 1;
    munmap(tbl, tbl->table_size);
    //close(tbl->shm_fd);
    shm_unlink(tbl->name);
  }
  // Code omission
}

这是开表功能

table_t *open_table(char *name, int record_size, int max_records){

  int shm_fd;
  int table_size;
  void* ptr;
  table_t* tbl;
  table_t controlBlock;
  db_info info;
  data_block data;

  table_size = max_records * sizeof(controlBlock) * sizeof(info) *
    sizeof(data);



  if((shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1){
    exit(EXIT_FAILURE);
  }

  ftruncate(shm_fd, table_size);
  ptr = mmap(NULL, table_size, PROT_WRITE | PROT_READ, MAP_SHARED, shm_fd, 
  0);
  tbl = ptr;
  tbl->shm_fd = shm_fd;
  tbl->table_size = table_size;
  tbl->max_records = max_records;
  tbl->record_size = record_size;
  if(tbl->numP >= 1){
    tbl->numP += 1;
  }
  else{
    tbl->numP = 1;
  }

  return tbl;
}

这些是我的结构

typedef struct{
  int dbInfoId;
  int deleted;
}db_info;

typedef struct{
  int shm_fd;
  int numP;
  int control_id;
  char *name;
  int table_size;
  int record_size;
  int max_records;
  db_info* dbInfo;
  void* db;
}table_t;


typedef struct{
  int id;
  void* record;
}data_block;

valgrind 说它是“大小为 8 的无效读取”

enter a command (just the number):
1. Add
2. Delete
3. Process
4. Close
5. # of processes
6. exit
4
table_size: 29360128
==6679== Invalid read of size 8
==6679==    at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679==    by 0x108F15: main (main.c:40)
==6679==  Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679== 
==6679== 
==6679== Process terminating with default action of signal 11 (SIGSEGV)
==6679==  Access not within mapped region at address 0x5654010
==6679==    at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679==    by 0x108F15: main (main.c:40)
==6679==  If you believe this happened as a result of a stack
==6679==  overflow in your program's main thread (unlikely but
==6679==  possible), you can try to increase the size of the
==6679==  main thread stack using the --main-stacksize= flag.
==6679==  The main thread stack size used in this run was 8388608.
--6679-- REDIR: 0x50db950 (libc.so.6:free) redirected to 0x4c30cd0 (free)
==6679== 
==6679== HEAP SUMMARY:
==6679==     in use at exit: 0 bytes in 0 blocks
==6679==   total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==6679== 
==6679== All heap blocks were freed -- no leaks are possible
==6679== 
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==6679== 
==6679== 1 errors in context 1 of 1:
==6679== Invalid read of size 8
==6679==    at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679==    by 0x108F15: main (main.c:40)
==6679==  Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679== 
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

标签: cposixvalgrind

解决方案


我想出了答案。tbl事实证明,在结构未映射后,我仍在尝试访问结构中的变量。所以为了解决这个问题,我只是在函数中创建了变量,并在取消映射tbl之前从结构中保存了我需要的内容。

void close_table(table_t *tbl){
  int size = tbl->table_size;
  char* name = tbl->name;
  int fd = tbl->shm_fd;
  printf("table_size: %d\n", tbl->table_size);
  if(tbl->numP > 1){
    tbl->numP -= 1;
    munmap(tbl, tbl->table_size);
    close(fd);
  }
  else if(tbl->numP == 1){
    tbl->numP -= 1;
    munmap(tbl, size);
    printf("unmap works\n"); fflush(stdout);
    shm_unlink(name);
    close(fd);
  }

推荐阅读