使用C++的Linux共享内存:分段错误

问题描述:

我正在关注Linux编程接口手册(第1004-1005页)。使用C++的Linux共享内存:分段错误

我知道这本书使用C.但我想在C++中实现相同的行为。即:通过共享内存在进程之间共享结构。

#include <iostream> 
#include <unistd.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 

using namespace std; 

struct my_pair { 
    int a; 
    int b; 
}; 

int main() 
{ 
    key_t key = ftok("aaaaa", 1); 
    int shmid = shmget(key, sizeof(my_pair), IPC_CREAT); 
    my_pair *numbers; 
    numbers = shmat(shmid, NULL, 0); 

    cout << numbers->a; 

    return 0; 
} 

它给我这个错误:

shteste.cpp: In function 'int main()':

shteste.cpp:18: error: invalid conversion from 'void*' to 'my_pair*'

据我所知,C++更为严格。如果我将shmat返回给(my_pair *),它会编译但在执行期间给我分段错误。

是否有可能(如何)使用C/C++的Linux/C共享内存设施?

我与编译:G ++ 4.4.7:G ++ shteste.cpp -o shteste -std =的C++ 0x

谢谢...

编辑:继所有sugestions,这是现在代码:

int main() 
{ 
key_t key; 

if ((key = ftok("/home/alunos/scd/g11/aaaaa", 1)) == (key_t) -1) { 
    perror("IPC error: ftok"); exit(1); 
} 

int shmid = shmget(key , sizeof(my_pair), IPC_CREAT | 0640); 

if (shmid == -1) { 
    perror("Could not get shared memory"); 
    return EXIT_FAILURE; 
} 

my_pair *numbers; 
void* mem = (my_pair*) shmat(shmid, NULL, 0); 
if (mem == reinterpret_cast<void*>(-1)) { 
    perror("Could not get shared memory location"); 
    return EXIT_FAILURE; 
} else { 
    numbers = reinterpret_cast<my_pair*>(mem); 
    cout << numbers->a; 
} 

return EXIT_SUCCESS; 
} 

AAAAA内容:notacat

[[email protected] ~]$ ./shteste

Could not get shared memory: Permission denied

+1

您确定错误是由您显示的代码产生的吗?如果你没有演员阵容,我会期待这个错误,就像'numbers = shmat(...)'。但演员应该照顾它。 –

+0

你是对的......我复制了“固定”代码......我投下的代码(因此不会抱怨转换)但出现分段错误。 –

+2

你应该检查'shmget'和'shmat'的返回值。 – bezet

这可能是一个权限问题。您可以检查返回值shmgetshmat并使用perror来打印这样的人类可读的错误消息。

#include <iostream> 
#include <unistd.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdio.h> 
#include <stdlib.h> 

using namespace std; 

struct my_pair { 
    int a; 
    int b; 
}; 

int main() 
{ 
    key_t key = ftok("aaaaa", 1); 
    int shmid = shmget(key, sizeof(my_pair), IPC_CREAT | 0777); 
    if (shmid == -1) { 
     perror("Could not get shared memory"); 
     return EXIT_FAILURE; 
    } 

    my_pair *numbers; 
    void* mem = (my_pair*) shmat(shmid, NULL, 0); 
    if (mem == reinterpret_cast<void*>(-1)) { 
     perror("Could not get shared memory location"); 
     return EXIT_FAILURE; 
    } else { 
     numbers = reinterpret_cast<my_pair*>(mem); 
     cout << numbers->a; 
    } 

    return EXIT_SUCCESS; 
} 
+0

您绝对正确:“无法获取共享内存位置:权限被拒绝”。我应该问系统管理员,还是有我作为用户/开发人员可以做的事情? –

+0

@VictorMarconi:不,你应该正确设置权限:-)看到我的答案! – Klaus

+0

我想感谢大家。所有的答案都有帮助......问题是各有所长。 错误的权限。因此,我不能再使用相同的密钥(ftok)。非常感谢。 –

根据ftok手册页:

The ftok() function uses the identity of the file named by the given 
pathname (which must refer to an existing, accessible file). 

使用现有文件的代码将工作。

或者您可以使用:

key = IPC_PRIVATE 

这将足以在这个例子中,但不会真正的IPC工作。

+0

我想感谢大家。所有的答案都有帮助......问题是各有所长。 错误的权限。因此,我不能再使用相同的密钥(ftok)。非常感谢。 –

你简单的忘记设置权限:

int shmid = shmget(key, sizeof(my_pair), IPC_CREAT | 0777); 

正如我在我的评论已经提到的,失败的命令的结果可以用strace的看到。

64 5327 shmget(0xffffffff, 8, IPC_CREAT|000) = 11534358 
65 5327 shmat(11534358, NULL, 0) = -1 EACCES (Permission denied)" 

如果您的文件“aaaaa”存在,代码适用于我。

这是一个权限问题。

the shmget() documentation

SYNOPSIS

#include <sys/shm.h> 

int shmget(key_t key, size_t size, int shmflg); 

...

DESCRIPTION

...

  • The low-order nine bits of shm_perm.mode are set to the low-order nine bits of shmflg.

您没有设置任何权限位。在您的通话shmflag的低位九个位都是零:

int shmid = shmget(key, sizeof(my_pair), IPC_CREAT); 

您需要设置适当的权限,这样的事情:

int shmid = shmget(key, sizeof(my_pair), IPC_CREAT|0640); 

您也将有可能使用ipcrm删除当前的共享内存段,因为它将保持不正确的permssions。即使您更改了代码,您的shmget()调用也会返回现有段的ID--由于缺少权限而无法附加的段。

首先,使用ipcs -a列出共享内存段,然后使用ipcrm -m shmidipcrm -M shmkey删除具有不正确权限的段。

+0

ipcs -a:没有列出共享内存段... –

+0

我想感谢所有人。所有的答案都有帮助......问题是各有所长。 错误的权限。因此,我不能再使用相同的密钥(ftok)。非常感谢。 –