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

共享内存程序中i设为4时while循环出现段错误的原因求助

共享内存程序段错误排查与修复

核心问题:栈空间溢出

当i=4时,size = 8*16^4 = 524288(512KB),代码里父子进程都在栈上声明了char str[size];。而进程的栈空间默认容量有限(通常在几MB以内,不同系统有差异),这么大的数组直接分配在栈上会触发栈溢出,直接导致段错误。你看到的错误出现在while循环附近,只是栈溢出的触发点巧合落在这个位置,本质和循环逻辑无关。

其他潜在问题及修复

  • 浮点数计算精度误差:pow是浮点函数,计算整数幂时可能出现精度丢失,导致size值不准确。改用整数运算替代:
    // 替换pow的整数计算方式,避免浮点精度问题
    int size = 8;
    for(int k=0; k<i; k++){
        size *= 16;
    }
    
  • 信号量未初始化:semget创建信号量后初始值是随机的,子进程的等待逻辑可能陷入死循环或异常。fork前要初始化信号量为0:
    int sem = semget(sem_key, 1, IPC_CREAT | 0666);
    semctl(sem, 0, SETVAL, 0); // 初始化信号量为0,父进程写完后再设为1
    
  • 数组越界:父进程循环里str[++j] = '\0';会访问str[size],超出数组边界(数组大小为size,索引范围是0~size-1)。正确写法:
    char *str = malloc(size);
    for(int j=0; j<size-1; j++){
        str[j] = '1';
    }
    str[size-1] = '\0';
    
  • 栈溢出彻底解决:把栈上的大数组改成malloc动态分配,堆空间的容量远大于栈,不会出现溢出问题。

修复后的完整代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>

int main()
{
    int i = 4, pid, status, shmid;
    key_t key, sem_key;
    
    // 整数运算计算size,避免浮点精度丢失
    int size = 8;
    for(int k=0; k<i; k++){
        size *= 16;
    }
    
    key = ftok(".", 'x');
    sem_key = ftok(".", 'y');
    if ((shmid = shmget(key, size, IPC_CREAT | 0666)) == -1) exit(1);
    char *shmPtr = shmat(shmid, 0, 0);
    if(shmPtr == (char*)-1) exit(1); // 检查共享内存挂载是否成功
    
    int sem = semget(sem_key, 1, IPC_CREAT | 0666);
    semctl(sem, 0, SETVAL, 0); // 初始化信号量为0
    
    pid = fork();
    
    if (pid == 0)
    {
        // 等待父进程写入完成
        while(semctl(sem, 0, GETVAL) != 1);
        // 动态分配内存存储读取内容
        char *str = malloc(size);
        if(!str) exit(1);
        strcpy(str, shmPtr);
        printf("子进程读取到的字符串长度:%zu\n", strlen(str));
        free(str);
        exit(0);
    }
    else
    {
        // 动态分配内存存储要写入的内容
        char *str = malloc(size);
        if(!str) exit(1);
        for (int j = 0; j < size-1; j++)
        {
            str[j] = '1';
        }
        str[size-1] = '\0';
        strcpy(shmPtr, str);
        semctl(sem, 0, SETVAL, 1); // 通知子进程可以读取
        free(str);
    }
    wait(&status);
    shmdt(shmPtr);
    shmctl(shmid, IPC_RMID, NULL);
    semctl(sem, 0, IPC_RMID);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 07:16:30