| | |
Playing with shared memory - problem with non 'simple' data types
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
Hi,
In my never ending quest to improve my C++, I'm trying to write a class that sets and reads shared memory. For the time being I am avoiding dealing with issues of concurrency/locking, etc. and starting small. I was successfully able to put into shared memory things like integers, char *, and even my own custom classes. (By making it a templated class).
However, I seem to be running into a problem if I attempt to use either a datatype or a class that contains a member that is of a datatype 'non native', ie like a 'string', or 'vector', I either crash or get garbage. I'm coming to the conclusion that I simply can't store these datatypes, given that the shared memory is 'C' code rather than C++. Could you confirm my assumption that it basically can't handle C++ types, or is it something in my code that would cause this problem?
Below is my SharedMemory class. (Note that all code is in the .h file right now - I'll separate it out when I use it more officially).
An example of usage would be (where Date is a custom class of mine that only contains native types like int's, time_t, etc.):
In my never ending quest to improve my C++, I'm trying to write a class that sets and reads shared memory. For the time being I am avoiding dealing with issues of concurrency/locking, etc. and starting small. I was successfully able to put into shared memory things like integers, char *, and even my own custom classes. (By making it a templated class).
However, I seem to be running into a problem if I attempt to use either a datatype or a class that contains a member that is of a datatype 'non native', ie like a 'string', or 'vector', I either crash or get garbage. I'm coming to the conclusion that I simply can't store these datatypes, given that the shared memory is 'C' code rather than C++. Could you confirm my assumption that it basically can't handle C++ types, or is it something in my code that would cause this problem?
Below is my SharedMemory class. (Note that all code is in the .h file right now - I'll separate it out when I use it more officially).
C++ Syntax (Toggle Plain Text)
extern "C" { #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> } template <class InputClass> class SharedMemory { private: key_t key; int shmid; InputClass *data; int SHM_SIZE; string fileName; void initialize() { if ((key = ftok(fileName.c_str(), 'R')) == -1) { throw DHException( "*** Could not connect to shared memory file [" + fileName + "] Check that the file exists...***" ); } /* connect to (and possibly create) the segment: */ if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) { throw DHException( "*** Could not use shared memory file: [" + fileName + "] Check that the allocated size is OK..***"); } data = (InputClass *) shmat(shmid, 0, 0); if (data == (InputClass *)(-1)) { throw DHException ( "*** Could not connect to shared memory file:(error 3):" + fileName); } } public: SharedMemory( string file ) { SHM_SIZE=sizeof(InputClass); fileName = file; initialize(); } SharedMemory( int size, string file ) { SHM_SIZE=size; fileName = file; initialize(); } void writeToSharedMemory( InputClass ic ) { *data = ic; } InputClass getFromSharedMemory( ) { return *data; } ~SharedMemory() { if (shmdt((char *)data) == -1) { throw DHException ( "Could not disconnect from shared memory file:" + fileName ); } } int getMemorySize() { return SHM_SIZE; }
An example of usage would be (where Date is a custom class of mine that only contains native types like int's, time_t, etc.):
C++ Syntax (Toggle Plain Text)
SharedMemory<Date> shm(1000, "DANTEST" ); while ( true ) { Date a; shm.writeToSharedMemory(a); screenLog<<"Just Placed:"<<a<<endl; sleep( 1 ); }
I'm not familiar with the libraries you are working with, but perhaps the "'non native', ie like a 'string', or 'vector'" issue is because they are not POD types?
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
Well I think I had plain old data confused with "things that need a deep copy; things for which a shallow copy would not suffice" -- that is, things that have dynamically-allocated memory rather than a simple array. Something like that.
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
First, I looked up a better description of POD. (This seems to say "yup" to your previous post.)
And I found a better description of deep copy. But essentially, I believe I was saying no. I'll qualify that with: perhaps you may, but you'd need to make a deep copy.[?]
•
•
•
•
Originally Posted by winbatch
Unfortunately, that went over my head. (Was that a no, you can't use dynamically allocated datatypes, or yes, you can)
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
That's interesting because I found that if I was reading and writing from the shared memory inside the same program it worked, but when trying to read those special parts (string, vector) from another program, that's when it failed. Could be because of the shallow/deep copy. I guess I'll have to look into how to deal with that. (Though if I'm simply using the std::string, I don't think it should be me who creates a proper copy constructor for it?)
•
•
•
•
Originally Posted by winbatch
That's interesting because I found that if I was reading and writing from the shared memory inside the same program it worked, but when trying to read those special parts (string, vector) from another program, that's when it failed.
#include <iostream>
#include <string>
#include <cstddef>
void showobject(const void *object, std::size_t size)
{
const unsigned char *byte = static_cast<const unsigned char *>(object);
for (size_t i = 0; i < size; ++i)
{
std::cout << std::hex << static_cast<int>(byte[i]);
}
std::cout << std::endl;
}
int main()
{
std::string text("hello world");
std::cout << text << " : ";
showobject(static_cast<const void *>(&text), sizeof text);
std::cout << text.c_str() << " : ";
showobject(static_cast<const void *>(text.c_str()), text.size());
std::cout << static_cast<const void *>(&text[0]) << std::endl;
return 0;
}
/* my output
hello world : 4454201000143b7b01000
hello world : 68656c6c6f20776f726c64
007B3B14
007B3B14
*/Let's say that Program A and Program B share a string using shared memory. That means each shares the whole first line (of the output displayed). But Program A's memory is different from Program B's, so Program A points to a "hello world", but Program B's memory at 007B3B14 is different.
Anybody feel free to bail me out if I'm completely off target here.
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
The diagnosis is accurate for the most part. Shared memory can't handle non-POD types. You could write a special purpose allocator for your standard containers, and unshared proxy objects that refer to a reasonable representation of the data in shared memory for everything else. I don't have a lot of experience with shared memory, so I won't try to give you code because it would be hopelessly broken. But this is a good problem to solve with threads rather than IPC and processes. 
I imagine that the proxy solution would be the easiest for you. You can serialize the data into, say, a C-style string representation for storage in shared memory, and the proxy class would be able to represent it as whatever object you need when you need it for a minor conversion cost. Here's a crude example for std::string:
With std::string and other standard containers you can write a custom allocator that knows about the shared memory and doesn't make your system cry when you use it. But that's harder, and depends heavily on knowing what you're doing with the shared memory library, which I don't, so I won't show you code.

I imagine that the proxy solution would be the easiest for you. You can serialize the data into, say, a C-style string representation for storage in shared memory, and the proxy class would be able to represent it as whatever object you need when you need it for a minor conversion cost. Here's a crude example for std::string:
C++ Syntax (Toggle Plain Text)
class string_proxy { std::string _str; char *_mem; public: std::string_proxy(char *addr): _mem(addr) {} std::string& get() { _str.assign(_mem); } void serialize() { memcpy(_mem, _str.c_str(), _str.size() + 1); } };
To make sure I understand, basically you write a function that takes your class contents, makes in effect a big string out of it. It's that string I put in shared memory. You then have a function that can take the big string and turn it back into the class contents again. I can then read the big string from shared memory and then reform the class.
If I've got you right, as long as I make my shared memory segment large enough to handle the size the string version I should be ok. Is that right?
If I've got you right, as long as I make my shared memory segment large enough to handle the size the string version I should be ok. Is that right?
![]() |
Other Threads in the C++ Forum
- Previous Thread: 2038 Problem
- Next Thread: Help me to delete a file
| Thread Tools | Search this Thread |
api array based beginner binary bitmap c++ c/c++ calculator char char* class code coding compile compiler console conversion count database delete deploy developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp homeworkhelper iamthwee ifstream input int java lib linkedlist linker list loop looping loops map math matrix memory multiple news node number numbertoword output parameter pointer problem program programming project proxy python random read recursion recursive reference rpg sorting string strings temperature template test text text-file tree unix url variable vector video visualstudio win32 windows winsock word wordfrequency wxwidgets






