gpt4 book ai didi

c - shmget 是如何分配内存的?无法使用线性寻址访问(地址边界错误)

转载 作者:太空宇宙 更新时间:2023-11-04 06:45:59 26 4
gpt4 key购买 nike

在下面的示例中,我尝试使用 shmget1 个整数和 10 个 foo 结构 分配内存并尝试线性访问它们。但是,它会因“地址边界错误”而出错。

对于 MacOS 系统(但在 Linux 上应该相同),我尝试分配两个数据结构应该占用的确切内存量,并尝试对它们进行线性字节寻址。

#include <stdio.h>
#include <sys/shm.h>

typedef struct {
int f1;
int f2;
} foo;

int main() {
// Size of memory. Consider, int size to be 4. (4 + 8 * 10 = 84 bytes)
const int shmsz = sizeof(int) + sizeof(foo) * 10;

// Create shared mem id.
const int shmid = shmget(IPC_PRIVATE, shmsz, 0666);
if (shmid < 0) {
perror("shmget failed.");
return 1;
}

// Pointer to the shared memory. Cast as char* for byte addressing.
char* shmemPtr = (char*) shmat(shmid, 0, 0);
if (*shmemPtr == -1) {
perror("shmat failed.");
return 1;
}

// The integer should point to the first 4 bytes. This is the same as
// the address pointed to by shmemPtr itself.
int* iPtr = (int*) shmemPtr[0];

// The 80 bytes for the 10 foos range from index 4 -> 83
foo* fPtr = (foo*) ((void*) shmemPtr[sizeof(int)]);

printf("i: %p\n", iPtr); // why is this 0x0 ?
printf("x: %p\n", fPtr); // why is this 0x0 ?

*iPtr = 0; // <-- This dereference crashes, probably since the address of iPtr is 0x0
}

分配内存并通过 shmat 接收到指向它的指针后,我尝试创建的指向已分配内存的任何指针都是 0x0 并且任何取消引用都会(理所当然地)崩溃该程序。我希望 int*foo* 是指向共享内存的有效指针。

我只是用 C/C++ 涉足一些系统方面的东西,如果我在这里遗漏了什么,请原谅我。

最佳答案

char* shmemPtr = (char*) shmat(shmid, 0, 0);

你现在有一个指向共享内存块的指针。它是一个char *,指向 block 的开始。到目前为止,还不错。

int* iPtr = (int*) shmemPtr[0];

因为 shmemPtr 是一个 char *shmemPtr[0] 是它的第一个字节。上面莫名其妙地将单个字节转换为 int *。当然,这没有任何意义。

您显然打算将 shmemPtr 重新解释为指向您的 int 的指针,因此您可以 *iPtr 以便读取第一个 int 您希望在您的共享内存块中。如果是这样,这应该是:

int* iPtr = (int*) shmemPtr;

那是针对 C 的。如果你正在使用 C++,你还可以帮助你的编译器帮助你避免搬起石头砸自己的脚:

int* iPtr = reinterpret_cast<int *>(shmemPtr);

锐意进取,我们来到:

foo* fPtr = (foo*) ((void*) shmemPtr[sizeof(int)]);

恭喜。 shmemPtr[sizeof(int)] 显然是 shmemPtr[4],或者共享内存块中的第五个字节;你只是拖着你的编译器,又踢又叫,把那个单字节首先转换成一个void *,然后再转换成一个foo *

显然,您打算计算该字节的地址,然后重新解释它。

foo* fPtr = (foo *)(shmemPtr + sizeof(int));   /* C default */

foo* fPtr = reinterpret_cast<foo *>(shmemPtr + sizeof(int)); /* Preferred in C++ */

由于特定于平台的对齐问题,这仍然可能 100% 正确,也可能不是 100% 正确。但这将是一个良好的开端。

关于c - shmget 是如何分配内存的?无法使用线性寻址访问(地址边界错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57940174/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com