C语言主、子进程共享内存数组实现及初始化类型转换报错解决
解决共享内存数组初始化时的指针-整数类型转换警告
问题根源
这个警告的核心是:你在master.c第17行把int*类型的指针直接赋值给了int类型变量,C语言里这两种类型不兼容,编译器会抛出类型不匹配的警告——要是不管,搞不好运行时直接触发内存访问错误崩溃。
通常这种错误出现在共享内存映射阶段:shmat()返回的是void*类型的内存地址,你错误地把它存到了普通int变量里,而不是指针变量。
一步步解决
1. 修正变量类型
首先把接收共享内存地址的变量改成指针类型,别用普通int。比如原来的错误代码可能是这样:
// 错误写法:master.c第17行 int shared_array = shmat(shmid, NULL, 0);
改成:
// 正确写法 int *shared_array; shared_array = (int*)shmat(shmid, NULL, 0); // 显式转成int*,避免编译器警告
注:C标准里void*可以隐式转成其他指针,但高版本GCC开-Wall会警告,显式转换能消掉这个提示。
2. 完整代码示例(结合你的文件结构)
config.h
#ifndef CONFIG_H #define CONFIG_H #define SHM_KEY 0x123456 // 自定义共享内存键值 #define ARRAY_SIZE 10 // 共享数组的元素个数 #endif
修正后的master.c
#include <stdio.h> #include <sys/shm.h> #include <stdlib.h> #include "config.h" int main() { int shmid; int *shared_array; // 创建共享内存段,大小要刚好装下整个数组 shmid = shmget(SHM_KEY, sizeof(int) * ARRAY_SIZE, IPC_CREAT | 0666); if (shmid == -1) { perror("shmget failed"); exit(1); } // 映射共享内存到当前进程空间 shared_array = (int*)shmat(shmid, NULL, 0); if (shared_array == (int*)-1) { // 检查映射是否失败 perror("shmat failed"); exit(1); } // 初始化共享数组 for (int i = 0; i < ARRAY_SIZE; i++) { shared_array[i] = i * 2; } // 这里可以加fork子进程的逻辑,或者等着user.c连接共享内存 // ... // 解除映射(进程退出会自动做,但手动写更规范) shmdt(shared_array); // 要是master是最后用共享内存的进程,销毁它: // shmctl(shmid, IPC_RMID, NULL); return 0; }
user.c(子进程/其他进程访问共享内存)
#include <stdio.h> #include <sys/shm.h> #include <stdlib.h> #include "config.h" int main() { int shmid; int *shared_array; // 获取已创建的共享内存段 shmid = shmget(SHM_KEY, sizeof(int) * ARRAY_SIZE, 0666); if (shmid == -1) { perror("shmget failed"); exit(1); } // 映射共享内存 shared_array = (int*)shmat(shmid, NULL, 0); if (shared_array == (int*)-1) { perror("shmat failed"); exit(1); } // 读取共享数组内容 printf("Shared array content:\n"); for (int i = 0; i < ARRAY_SIZE; i++) { printf("%d ", shared_array[i]); } printf("\n"); shmdt(shared_array); return 0; }
3. 编译时的小技巧
编译时加-Wall开全警告,方便排查潜在问题,比如:
gcc master.c -o master -std=c99 -Wall gcc user.c -o user -std=c99 -Wall
要注意的坑
- 共享内存的大小必须算对:
sizeof(int) * ARRAY_SIZE,不然数组越界直接搞崩进程。 - 一定要检查
shmat()的返回值:映射失败会返回(void*)-1,转成int*后判断才准确。 - 不用共享内存时记得解除映射,最后一个用的进程要销毁共享内存,不然会残留系统资源。
内容的提问来源于stack exchange,提问作者Matteo Pagliarello
相关产品推荐
相关产品推荐

