I am writing a program on a hotel reservation system and have declared a struct Room as follows:
struct Room { bool isavailable; bool ispaid; string customer; string date; };
I use a variable read from an input file to create an array of n structs which is all the rooms in the hotel.
struct Room* rooms = new Room[numOfRooms];
I then create the shared memory space and attach it, but when I try to access it after, it doesn’t seem to work.
//creates shared memory space if((shmid = shmget(shmkey, 1000, IPC_CREAT | 0666)) < 0) { perror("Failed to allocate shared mem"); exit(1); } //attaches shared memory to process Room* shared_memory; shared_memory = (Room* ) shmat(shmid, NULL, 0); if(!shared_memory) { perror("Error attaching"); exit(0); } struct Room *PTR = rooms; //temp pointer to rooms array cout << "test: " << rooms[1].customer << endl; //print before storing in shared memory rooms = (struct Room*) shared_memory+sizeof(int); //places rooms array in shared memory delete [] PTR; //deletes the memory location where rooms was stored before being in shared memory cout << "test: " << rooms[1].customer << endl; //print after storing in shared mem
As you can see I have a cout statement before moving rooms into shared memory which prints the correct thing, but the after cout is empty. Any help would be greatly appreciated, thanks.
Advertisement
Answer
rooms = (struct Room*) shared_memory+sizeof(int); //places rooms array in shared memory
This line does not do what your comment says. First, shared_memory
is already declared as Room* shared_memory
so the cast is unnecessary. Adding sizeof(int)
(let’s assume that is 4) to a pointer will make the pointer point to the 4th such element, that is if shared_memory
was pointing to the first element of a Room arr[N]
array, the expression shared_memory + i
is equal to &arr[i]
. In this case, shared_memory+sizeof(int)
is a pointer to the 4th (or sizeof(int)
‘th) element — or rather where that element would be in the shared_memory
because you just created the shared memory and haven’t put any actual Room
s in there yet.
Finally, rooms = ...
just assigns a value to the pointer. So now the rooms
variable (which is a pointer, just a number basically) points to the place where the 4th Room
object in the shared_memory
array would be. It’s not copying the array created with new Room[numOfRooms]
or anything like that.
See also: How do pointer to pointers work in C?
What you want to do is copy the objects into shared memory. For that in general you could use std::copy
like so:
std::copy(&rooms[0], &rooms[numOfRooms], shared_memory);
But the problem will be that std::string
contains a pointer to a char
array which you can assume to be allocated with new char[length_of_string]
. (This is a simplified version of the truth, but enough for this.) The std::copy
above will not move this internal array into shared memory, therefore it will not work if you map the shared memory in another process and access the string data. (You might read memory garbage or you might segfault when trying to access unmapped memory.) To solve this, you need to use an allocator type that can allocate from the shared memory, or store strings inline with something like a struct ShortString{ char data[/*max length*/ 20]; }
. You’ll want to search for or post another question if you need help with that.