You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共享内存中分配tmp_buf结构体后strncpy触发段错误问题

解决共享内存中结构体指针导致的段错误问题

我来帮你分析这个段错误的问题——这是共享内存使用中很常见的一个坑!

问题根源

你把tmp_buf结构体放在了mmap映射的共享内存里,其中的char* data是一个指针类型字段。但这里的关键问题是:

  • 刚映射完共享内存时,buf_ptr->data是一个未初始化的随机值,直接用它来写数据,本质是往一个无效的虚拟内存地址写入,必然触发段错误。
  • 就算你在当前进程里手动给buf_ptr->data赋值为(char*)buf_ptr + sizeof(tmp_buf)(也就是共享内存中预留的数据区域起始地址),这个指针值在其他进程里也是无效的——因为不同进程映射共享内存到虚拟地址空间的位置可能不一样,跨进程直接传递指针是行不通的。

正确解决方案:用偏移量代替指针

要在共享内存中安全地存储指向共享区域内数据的“引用”,应该使用偏移量而不是直接的指针。偏移量记录的是数据区域相对于结构体起始地址的字节数,这样不管共享内存被映射到哪个虚拟地址,都能通过结构体指针加上偏移量计算出正确的数据地址。

修改后的代码示例

1. 重新定义结构体

把char* data替换成偏移量字段:

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define MAX_BUFFERS 10

// 用偏移量代替指针,跨进程共享更安全
typedef struct {
    int size;
    off_t data_offset; // 数据区域相对于结构体起始地址的偏移字节数
} tmp_buf;

2. 初始化共享内存并写入数据

int main() {
    const size_t shm_total_size = sizeof(tmp_buf) + MAX_BUFFERS * 1024;
    int shm_fd = shm_open("/my_shared_memory", O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open failed");
        return 1;
    }

    // 设置共享内存大小
    if (ftruncate(shm_fd, shm_total_size) == -1) {
        perror("ftruncate failed");
        close(shm_fd);
        return 1;
    }

    // 映射共享内存到当前进程地址空间
    tmp_buf* buf_ptr = mmap(NULL, shm_total_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (buf_ptr == MAP_FAILED) {
        perror("mmap failed");
        close(shm_fd);
        return 1;
    }

    // 初始化偏移量:数据区域紧跟在结构体之后,偏移量就是结构体的大小
    buf_ptr->data_offset = sizeof(tmp_buf);

    // 计算数据区域的实际地址
    char* data_addr = (char*)buf_ptr + buf_ptr->data_offset;

    // 安全写入测试数据
    const char* test_content = "Hello from shared memory!";
    strncpy(data_addr, test_content, strlen(test_content) + 1);
    buf_ptr->size = strlen(test_content) + 1;

    printf("Successfully wrote data: %s\n", data_addr);

    // 后续操作...

    // 清理资源
    munmap(buf_ptr, shm_total_size);
    close(shm_fd);
    shm_unlink("/my_shared_memory");

    return 0;
}

额外注意事项

  • 同步问题:如果是多进程共享这块内存,一定要用信号量、互斥锁等同步机制,避免多个进程同时读写导致数据损坏。
  • 偏移量类型:使用off_t类型是因为它是标准的偏移量类型,能覆盖大多数系统上的内存偏移范围。
  • 内存大小检查:确保mmap的总大小确实是sizeof(tmp_buf) + MAX_BUFFERS*1024,避免越界访问。

内容的提问来源于stack exchange,提问作者Tejas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:54:10