linux上写的一个简单的C++共享内存程序:segmentation fault
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8189638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
A simple C++ shared memory program written on linux: segmentation fault
提问by Terry Li
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct LOCK {
string name;
string type;
vector <string> pids;
};
int main ()
{
int segment_id;
LOCK* shared_memory;
struct shmid_ds shmbuffer;
int segment_size;
const int shared_segment_size = 0x6400;
/* Allocate a shared memory segment. */
segment_id = shmget (IPC_PRIVATE, shared_segment_size,
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
/* Attach the shared memory segment. */
shared_memory = (LOCK*) shmat (segment_id, 0, 0);
printf ("shared memory attached at address %p\n", shared_memory);
/* Determine the segment's size. */
shmctl (segment_id, IPC_STAT, &shmbuffer);
segment_size = shmbuffer.shm_segsz;
printf ("segment size: %d\n", segment_size);
/* Write a string to the shared memory segment. */
//sprintf (shared_memory, "Hello, world.");
shared_memory -> name = "task 1";
shared_memory -> type = "read";
(shared_memory -> pids).push_back("12345");
(shared_memory -> pids).push_back("67890");
/* Detach the shared memory segment. */
shmdt (shared_memory);
/* Reattach the shared memory segment, at a different address. */
shared_memory = (LOCK*) shmat (segment_id, (void*) 0x5000000, 0);
printf ("shared memory reattached at address %p\n", shared_memory);
/* Print out the string from shared memory. */
//printf ("%s\n", shared_memory -> name);
cout << "Name of the shared memory: " + shared_memory -> name << endl;
/* Detach the shared memory segment. */
shmdt (shared_memory);
/* Deallocate the shared memory segment. */
shmctl (segment_id, IPC_RMID, 0);
return 0;
}
I got the code from a tutorial on shared memory. It worked until I defined struct LOCK and tried to write LOCKs instead of char* into the shared memory.
我从共享内存教程中获得了代码。它一直有效,直到我定义了 struct LOCK 并尝试将 LOCK 而不是 char* 写入共享内存。
Could someone please help me figure out the problem here that causes the segmentation fault?
有人可以帮我找出导致分段错误的问题吗?
采纳答案by K-ballo
You are placing vector
s and string
s into shared memory. Both those classes allocate memory of their own, which will be allocated within the address space of whatever process generates the allocation, and will produce a segfault when accessed from the other process. You could try specifying allocators to use that shared memory, but since in C++03 allocators are assumed to be stateless I'm not sure if it will be possible.
您将vector
s 和string
s 放入共享内存中。这两个类都分配自己的内存,这些内存将在任何进程生成分配的地址空间内分配,并且在从另一个进程访问时会产生段错误。您可以尝试指定分配器以使用该共享内存,但由于在 C++03 中分配器被假定为无状态,我不确定这是否可行。
Consider checking out how Boost.Interprocess does it.
考虑看看 Boost.Interprocess 是如何做到的。
回答by Kerrek SB
You have a number of problems. The obvious one is that you don't constructyour object. In opaque form, you are currently doing:
你有很多问题。显而易见的一个是你不构造你的对象。以不透明形式,您目前正在执行:
class Foo;
Foo * p = get_memory();
p->bar = 5; // ouch!
What you should be doing, at the very least:
你至少应该做的是:
void * addr = get_memory(sizeof(Foo));
Foo * p = ::new (addr) Foo;
// do work
p->~Foo(); // done
(Just replace Foo
by LOCK
for your situation.)
(只需Foo
根据LOCK
您的情况替换为。)
However, it gets more complicated: vector
and string
require dynamic allocations themselves. That memory must live in the same address space as your LOCK
. So the standard way to solve this is to write your own allocator and pass that:
然而,它变得更加复杂:vector
并且string
需要动态分配本身。该内存必须与您的LOCK
. 所以解决这个问题的标准方法是编写你自己的分配器并传递它:
template <template <typename> class Alloc>
struct Lock
{
typedef std::basic_string<char, std::char_traits<char>, Alloc<char>> shared_string;
shared_string name;
shared_string type;
std::vector<shared_string, Alloc<shared_string>> pids;
};
Finally, you have to write a conforming allocator class that puts memory in the same address space as the one in which your LOCK
object will ultimately go:
最后,您必须编写一个符合标准的分配器类,该类将内存放在与您的LOCK
对象最终将进入的地址空间相同的地址空间中:
template <typename T>
class shared_allocator { /* write this! */ }
typedef Lock<shared_allocator> LOCK;
回答by Bretzelus
I know it is very long time ago. But I was searching how-to (remember) about shared mem and this thread is interesting.
我知道这是很久以前的事了。但是我正在搜索有关共享内存的操作方法(记住),这个线程很有趣。
My Two cents to the demander :
我给需求方的两分钱:
- Please consider that reading and writing to SharedMemory is exactly like reading and writing into a FileSystem.
Shared Memory ID == file_handle from open(...);
So... How do you CORRECTLY serialize and then read-write std::string or even std::vector into a FILE ? Do you really 'expand/shrink' a std::string or std::vector from within a FILE ??
- 请考虑读取和写入 SharedMemory 与读取和写入文件系统完全一样。
共享内存 ID == file_handle from open(...);
那么......你如何正确序列化然后将 std::string 甚至 std::vector 读写到 FILE 中?您真的从 FILE 中“扩展/收缩”了 std::string 或 std::vector 吗?
Thank you :)
谢谢 :)