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

Linux-Ubuntu环境下共享内存动态分配变量被其他进程修改不生效求助

问题根因定位
  • 致命错误1:共享内存申请大小计算错误。你在test.h中定义了typedef int* INT,也就是INT本质是int类型指针,不是int本身。START程序中shmget(shmKEY,4*sizeof(INT),IPC_CREAT | 0664)计算得到的是4个指针的大小(64位系统下为32字节),和你实际需要存储的4个int值的空间要求不匹配。
  • 致命错误2:SECOND程序shmget参数错误。你写的是shmget(shmKEY,0,IPC_CREAT | 0664),当第二个参数为0且携带IPC_CREAT标记时,如果共享内存创建失败/key不匹配,会直接生成一个大小为0的共享内存,后续操作该内存地址会触发段错误,程序直接崩溃退出,所以你看不到DEBUG0之后的输出,看起来就像操作被跳过了。
  • 通用问题:所有系统调用都没有加返回值校验,无法定位具体失败步骤。ftok、shmget、shmat、execl调用失败的场景你都没有做判断,出问题无法快速定位。
  • 额外不规范点:typedef int* INT这种写法非常容易混淆类型,极易出现sizeof计算错误的问题,非常不推荐。
修改方案

1. 修正test.h

取消容易混淆的指针类型定义:

#ifndef _TEST_H
#define _TEST_H
typedef int INT;
#endif

2. 修正START程序代码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include "test.h"

int main(){
    key_t shmKEY;
    shmKEY= ftok(".",'a');
    if(shmKEY == -1) {
        perror("ftok error");
        return 1;
    }
    // 修正共享内存大小为4个int的总长度
    int shmID = shmget(shmKEY, 4 * sizeof(int), IPC_CREAT | 0664);
    if(shmID == -1) {
        perror("shmget error");
        return 1;
    }
    int* A;
    A = shmat(shmID, NULL, 0);
    if(A == (void*)-1) {
        perror("shmat error");
        return 1;
    }

    A[0] = 1;
    A[1] = 2;
    A[2] = 3;
    A[3] = 4;

    for(int i = 0; i < 4; i++){
        printf("[%d]", A[i]);
    }
    printf("\n");

    pid_t pid;
    pid = fork();
    if(pid < 0){
        perror("fork error");
        return 1;
    }
    else if(pid == 0){
        execl("./SECOND", "./SECOND", NULL);
        perror("execl error");
        exit(1);
    }

    if(pid > 0){
        wait(NULL);
        for(int i = 0; i < 4; i++){
            printf("[%d]", A[i]);
        }
        printf("\n");
    }

    shmdt(A);
    shmctl(shmID, IPC_RMID, 0);
    return 0;
}

3. 修正SECOND程序代码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>

int main(){
    key_t shmKEY;
    shmKEY = ftok(".", 'a');
    if(shmKEY == -1) {
        perror("ftok error");
        return 1;
    }
    // 去掉IPC_CREAT标记,直接打开已创建的共享内存
    int shmID = shmget(shmKEY, 4 * sizeof(int), 0664);
    if(shmID == -1) {
        perror("shmget error");
        return 1;
    }
    int* A;
    A = shmat(shmID, NULL, 0);
    if(A == (void*)-1) {
        perror("shmat error");
        return 1;
    }
    printf("DEBUG0\n");
    A[0] = A[0] + 1;
    A[1] = A[1] + 1;
    A[2] = A[2] + 1;
    A[3] = A[3] + 1;

    for(int i = 0; i < 4; i++){
        printf("[%d]", A[i]);
    }
    printf("\n");
    printf("DEBUG1\n");
    shmdt(A);
    return 0;
}

4. 修正Makefile

注意Makefile中的缩进必须是Tab,不能是空格:

All: START SECOND

START:main.o
	gcc main.o -o START

SECOND:second.o
	gcc second.o -o SECOND

second.o:second.c test.h
	gcc -c second.c        

main.o: main.c test.h
	gcc -c main.c

clean:
	rm *.o START SECOND        
验证步骤
  1. 如果之前有残留的错误共享内存,可执行ipcs -m查看共享内存列表,用ipcrm -m 共享内存ID删除残留
  2. 执行make clean清理旧编译产物,再执行make编译
  3. 运行./START即可得到预期输出:
[1][2][3][4]
DEBUG0
[2][3][4][5]
DEBUG1
[2][3][4][5]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:06:08