访问共享内存中的指针时,我遇到了一种“未定义的行为”。
基本上,该进程初始化共享内存段,并为灵活数组分配内存(其元素数量在运行时决定) - 注意:
product_1
在createProductArray函数中使用realloc分配。
然后,在 fork 自身后,他通过调用 execve 来替换程序:新程序将附加到共享内存,读取前一个共享内存地址,与当前共享内存地址分离,并附加到前一个地址;这样做是因为我需要访问
product_1
,它没有固定的大小,但取决于运行时生成的 my_struct_2
的数量。
我可以毫无问题地访问变量
foo_1
,我猜是因为它不是动态分配的,即使新程序没有使用shmat(shmid, NULL, 0)
附加到以前的地址。
我已经检查了
product_1
和 SharedMemorySegment
的地址,看起来我正确地附加到了正确的地址:但我仍然无法访问product_1。
注意:在第一个进程中,就在写入共享内存段之后,printf("product_1[0].boo_1: %d\n", sharedMemory->myArray[0].product_1[0].boo_1);
工作正常;我不会释放分配的资源。
我错过了什么?
结构:
struct my_struct2{
int boo_1;
};
struct my_struct1 {
double foo_1;
struct my_struct2 *product_1;
};
父进程:
struct SharedMemorySegment {
int foo;
void *sharedMemoryAddress;
struct my_struct1 myArray[];
};
size_t shmp_size = sizeof(struct SharedMemorySegment) + (countProc * sizeof(struct my_struct1));
sharedMemory = (struct SharedMemorySegment *) malloc(shmp_size);
if (sharedMemory == NULL) {}
if((shmid = shmget(SHM_KEY, sizeof(struct SharedMemorySegment) + (countProc * sizeof(struct countProc)), IPC_CREAT | S_IRUSR | S_IWUSR)) == -1){}
if ((sharedMemory = shmat(shmid, NULL, 0)) == (void*) -1){}
shmp->sharedMemoryAddress = (void *)shmp;
struct Product *product_1 = NULL;
product_1 = createProductArray(product_1_data);
sharedMemory->myArray[j].product_1 = malloc(count_1 * sizeof(struct my_struct2));
//sharedMemory->myArray[j].product_1 = product_1;
memcpy(sharedMemory->myArray[j].product_1, product_1, sizeof(struct my_struct2) * count_1);
// Other code here..
execve(...)
新计划:
// Code here..
// Attach to the previous address
if ((sharedMemory = (struct SharedMemorySegment *)shmat(shmid, address, 0)) == (void *)-1) {...}
// Accessing the dinamically allocated pointer gives me undefined behavior.
printf("product_1[0].boo_1: %d\n", sharedMemory->myArray[0].product_1[0].boo_1);
在大多数现代操作系统上,每个程序都有自己的虚拟地址空间。当您将程序连接到共享内存区域时,它将添加到该程序的地址空间中。然而,每个程序中添加它的位置可能不一样。实际上,这意味着在设计使用共享内存的程序时,通常不应将任何指针写入共享内存区域。
要仔细检查您的情况是否发生这种情况,您可以尝试在每个程序中打印出
sharedMemoryAddress
的值。它应该(或者至少可能)有所不同。如果不同,则意味着写入 shm 的地址仅适用于写入它的程序。
免责声明:我没有在这里详细介绍您的代码,手头可能还存在其他问题。