共享内存中动态分配内存为何会重置为初始化值?
问题原因
核心问题在于共享内存仅存储了SharedMemory结构体本身,而结构体中的solutionVector指针指向的是进程私有堆内存,不属于共享内存区域:
- 主进程调用
initializeSharedMemory时,createVector和calloc分配的是主进程自身的私有堆内存,这块内存不会被共享给子进程。 - 子进程fork后,共享内存里的
solutionVector指针值会被复制,但该指针在子进程地址空间中指向的是子进程自己的私有堆(fork操作会复制父进程的堆空间),子进程更新的是自己私有堆内的vector数据,这些修改无法同步到主进程的私有堆。 - 主进程最终打印时,访问的是自己初始分配的私有堆内的vector,因此显示的是初始全0值。
- 输出中
distance:21是正确的,因为bestSolutionDistance是结构体内部的int类型变量,属于共享内存区域,所以能正常同步。
解决方法
提供两种针对性修正方案:
方案1:将Vector内容嵌入共享内存结构体(固定大小场景)
如果Vector的大小是提前确定的,直接修改SharedMemory结构体,用数组替代指针:
// 根据实际业务调整最大向量长度 #define MAX_VECTOR_SIZE 100 typedef struct{ int bestSolutionDistance; int BestSolutionFoundByProcess; int BestSolutionFoundInIterations; int solutionVector[MAX_VECTOR_SIZE]; // 直接嵌入数组 } SharedMemory;
修改initializeSharedMemory函数,直接初始化共享内存内的数组:
void initializeSharedMemory(SharedMemoryPtr sharedMemoryPtr, int size) { sharedMemoryPtr->bestSolutionDistance = 1e9; sharedMemoryPtr->BestSolutionFoundByProcess = -1; sharedMemoryPtr->BestSolutionFoundInIterations = -1; // 直接初始化共享内存中的数组 memset(sharedMemoryPtr->solutionVector, 0, size * sizeof(int)); }
主进程计算共享内存大小直接使用sizeof(SharedMemory)即可。
方案2:让指针指向共享内存内部区域(动态大小场景)
如果Vector大小是动态的,需要把Vector的内存也纳入共享内存范围:
- 计算共享内存总大小:结构体大小 + Vector所需内存
int vectorSize = distanceMatrix->size; size_t sharedMemoryTotalSize = sizeof(SharedMemory) + vectorSize * sizeof(int); int shm_fd = createOrOpenSharedMemory(SHM_NAME, sharedMemoryTotalSize);
- 映射共享内存后,让
solutionVector指向共享内存结构体后的区域:
sharedMemoryAllocatedPtr = mapSharedMemory(shm_fd, sharedMemoryTotalSize); // 让指针指向共享内存内部的数组区域 sharedMemoryAllocatedPtr->solutionVector = (int*)((char*)sharedMemoryAllocatedPtr + sizeof(SharedMemory));
- 修改
initializeSharedMemory函数,直接初始化共享内存内的数组:
void initializeSharedMemory(SharedMemoryPtr sharedMemoryPtr, int size) { sharedMemoryPtr->bestSolutionDistance = 1e9; sharedMemoryPtr->BestSolutionFoundByProcess = -1; sharedMemoryPtr->BestSolutionFoundInIterations = -1; memset(sharedMemoryPtr->solutionVector, 0, size * sizeof(int)); }
这样solutionVector指向的是共享内存的一部分,所有进程访问的是同一块内存,修改会实时同步。
额外注意事项
- 多进程场景下,必须用信号量等同步机制保护共享内存的读写,避免数据竞争。
- 原代码中
calloc分配的dataTest不再需要,需同步修改initializeVector函数,使其直接操作solutionVector指向的共享内存数组。
内容的提问来源于stack exchange,提问作者Hoshizora
相关产品推荐
相关产品推荐

