shmat(3) 函数 returns 0xffffffffffffffff 地址

shmat(3) function returns 0xffffffffffffffff address

我一直在努力使用 IPC 共享内存。我正在尝试通过 BSD TCP 套接字编写简单的服务器/客户端程序通信。服务器是多线程的,并为用户之间的多个并行国际象棋对决提供服务。每个线程只与一个用户相关联。要共享有关移动和决斗状态的数据,我想使用共享内存,因为服务器控制几乎所有内容。

我创建了决斗 class 并且每次决斗请求被接受时,服务器都会创建新的共享内存并将密钥传递给用户:

this->key_kernel = (this->key_kernel + 17) % 1000000;
int shmid = shmget(this->key_kernel, sizeof(Duel), 0666 | IPC_CREAT);

challenger->set_shmkey(this->key_kernel);
challenged->set_shmkey(this->key_kernel);

Duel *duel = (Duel *)shmat(shmid, (void *)0, 0);
duel->init_duel(challenger, challenged);
shmdt(duel);

当控制通信的线程注意到决斗开始时,它会做类似的事情:

shmid = shmget(current_user->get_shmkey(), sizeof(Duel), 0666 | IPC_CREAT);
duel = (Duel *)shmat(shmid, (void *)0, 0);

并且使用决斗的方式。它工作正常,但是......最多五场决斗。我注意到每次在 5 次决斗(即 5 次决斗接受)之后,无论完成还是进行中 - 程序都会失败(分段错误)

经过调查,我注意到应该由 shmat 附加到共享内存的决斗指针此时为 0xffffffffffffffff。我也注意到一些 errno 24.

即使是一些草率的修复,比如检查指针是否不是 0xffff,我也会很感激……但我真的不知道这是否可能。类似于:

int *a;
a = nullptr;
if (a == nullptr) {...}

对于 nullptr 这很容易,但我不知道如何将自定义(即决斗指针)转换为 char* 或其他东西来比较它。

来自男人:

shmat() returns the address at which the shared memory segment has been mapped into the calling process' address space when successful, shmdt() returns 0 on successful completion. Otherwise, a value of -1 is returned, and the global variable errno is set to indicate the error.

您看到的 0xffffffffffffffff 指针 -1 表示错误。

向您的程序添加一个 if,它检查 shmatshmget 的 return 值是否有错误。在 if 中,您可以使用 perror 函数打印一条错误消息,告诉您出了什么问题。

这是一般规则。您应该始终检查系统调用的 return 个值:

a = system_call_x();
if (a == (void*) -1) {
    perror("system_call_x failed, exiting");
    exit(1);
}