Storing and accessing an array of struct from shared memory - c++

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.

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 Rooms 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.

Related

c++ memory allocation howto

I am just starting C++ and I can't understand how my code works:
Ok I allocate memory, but at the time of the allocation nobody knows the size of the memory to be allocated. But still the code works.
How much memory is allocated? How the compiler knows how much memory I will need?
EDIT:
Sorry if my question was not clear. Let me please try clarify it. So I dynamically allocate some memory in the heap by using my pointer. But since there is no text in the sting variable, in my opinion it is quite difficult to know how much text (bytes) I will enter via getline.
I tried asking the size of two different text literals, and yes they are different in size.
sizeof("") // is 1 (because of the ending 0 maybe?)
sizeof("sometext") // is 9
But for the string: the sizeof gives me 4 both times. It's clear that the sizeof() gives me the length of the pointer pointing to the string.
How can I allocate memory? If I allocate memory for a new string, only allocates to a pointer pointing to the memory address of the first character in the string?
Obviously the characters I enter must be stored somewhere. And I first allocate the memory, and then I load some text into it.
Edit 2: make the edited code to look code, not plain text.
//Edit:
string a,b = "sometext";
cout << sizeof(a) << endl; //4
cout << sizeof(b); //4
//--------------------------------------------------------
#include <iostream>
#include <string>
#include <exception>
using namespace std;
int main()
{
//Defining struct
struct musicCD
{
string artist, title; // artist of the CD
};
//Memory allocation
musicCD *ptr;
try{ptr = new musicCD;}
catch(bad_alloc){cerr << "Out of memory :(";return -1;}
catch(...){cerr << "Something bad happened :O !";return -1;
}
//Get the data to store:
cout << "Please enter the data for the CD!' " << endl;
cout << "Please enter the artist: ";getline(cin, ptr->artist); cout << endl;
//Write out the data
cout << "The data entered: " << endl;
cout << "The artist performing is: \t" << ptr->artist << endl;
delete ptr;
return 0;
}
It seems like you are confused about how std::string, or any dynamic container, handles the fact that it's memory requirements are not predetermined. std::string for example does not store it's character data internally. Simply put, it contains a pointer that points to another dynamic allocated buffer which contains the actual data. std::string has constructors, a destructor and assignment operators that automatically manage the extra buffer, which contains the actual character data. This including reallocating, copying the data, updating the internal pointer and freeing the previous buffer when extra storage is needed. The size of the buffer that contains the actual data does not count towards the size of std::string, only the pointer to it does. Every instance of std::string, throughout it's lifetime, only directly contains a constant number of members which all have constant sizes. In c++ all types have a compile time constant size.
See Rule of five for a simplified implementation of string showing how it works. The size of the class rule_of_five from this example is simply the size of char* regardless of the content of the buffer pointed to by this pointer. The actual buffer is allocated later, during or after construction, which is after the initial allocation for the object itself has already finished.
Edit: There are some cases where a string can store it's character data internally when dealing with very short strings. This is an optimization not generally seen in other containers. See this answer.

Values still accessible after I call delete, c++ [duplicate]

This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 3 years ago.
I have to classes, one Employee class and one BankAccount class, the employee class has the BankAccount class as a private variable pointer.
This is what I am trying to do:
I need to set up all the BankAccounts in each Employee with values
then I delete all BankAccounts for every Employee at the end of the function.
I use a member function setter in Employee to set up the BankAccount pointer. BankAccount has one private variable and that is amount. Later I call delete on a pointer that should point to each BankAccount's memory address. After I call print to see the values of the bank for each Employee and it is still printing values for each BankAccount
If I call delete shouldn't the memory on heap be delete and when print is called not output anything for BankAccount?
Here is the code:
vector<Employee*> employees;
//get employee full name & salary and return
employees.push_back(get_employee_info());
//setup their bank account
setup_bank(employees);
//make temp pointer to store bank memory address
BankAccount * tempBankPtr;
for (int i =0; i < employees.size(); i++) {
tempBankPtr =employees[i]->get_bank();
delete tempBankPtr // delete the heap object that pointer is pointing at
}
//print values
for (int i =0; i< employees.size(); i++) {
employees[i]->print();
}
code for print
void Employee:: print() const {
cout << "First name is: " << firstName << "\n";
cout << "Last name is: " << lastName << "\n";
BankAccount* bankholder = NULL;
bankholder = get_bank();
if(bankholder != NULL)
cout << "Account Balance is: " << get_bank()->get_amount() << "\n"; //prints values
}
getter for bank
BankAccount* Employee::get_bank() const{
return bank;
}
this is called in setup_bank
void Employee::set_bank(Employee* e, double amount){
bank = new BankAccount(amount);
}
If I call delete shouldn't the memory on heap be delete and when print is called not output anything for BankAccount?
No.
Deleting the object at that location in memory means it does not exist any more, so you're not allowed to access it.
It does not mean your program will magically print "nothingness" to protect you from this mistake.
Your program therefore has undefined behaviour; you must make sure you do not dereference an invalid pointer!
A very nice explanation of how free works.
When you call delete on the pointer and unlike as it has been suggested above you should only expect the following
Execute the destructor
The memory is not set to zero or any other magical value, since that is a very very expensive operation. When free is going to be called and if furthermore this will cause a call to sbrk is largely implementation dependent. The latter returns memory to the operating system.
For example AIX is well known to have a quite complex mechanism for memory management. What you should expect is that actually the block of memory will be marked as reallocatable , and new objects might overwrite your after the address pointed. Until this happens, you old staff are most probably still there.
Furthermore unlike stated before you can very well access it for as long as the data segment has not been reduced, and actually the object still exists , it is just that only you know about it.
That is why in this case you do not get SIGSEGV as you would expect. You probably get it later when you allocate something and the addressing a pointer in that memory area executes arbitrary code.
Accessing a delete pointer is undefined behavior and deleting it a second time is even more dangerous. To alleviate the situation there are many techniques , the most simple being encapsulation and deleting the pointer on the class destructor. You should set the pointer to nullptr.
Simplicity stops here, since you have to apply the rule of three (and a half ) . Thus it is better to work with shared or unique pointer provided by c++11 , and ignore these issues for now.

c++ dynamic stuct pointer to char array

I'm having trouble dynamically assigning memory to a char array inside a pointer to a struct.
This is a homework assignment that has to use this struct outline:
struct Student
{
char *namePtr;
unsigned int score;
};
this is the part im having trouble with though
/***************************
* takes value from temporary value and puts into dynamic allocated Student array
***************************/
bool updateStructPtr(Student **info, unsigned int index, char *name, unsigned int score)
{
try
{
info[index]->namePtr = new char [strlen(name)+1];
if(DEBUG) cout << "size for dynamic char: " << strlen(name)+1 << endl << endl;
//copy char array into new array
strcpy(info[index]->namePtr, name);
info[index]->score = score;
}
catch (bad_alloc & param)
{
info[index]->namePtr = NULL;
return false;
}
return true;
}
my prof said:
A glance at your code reveals that you do not seem to be dynamically allocating memory for the Student structure as specified in the first sentence of step 3-2 of the algorithm I provided you.
3-2. Dynamically allocate memory for a Student structure. Place the address of this Student structure in the array of structure pointers. You will also need to dynamically allocate just enough memory to store the name. Do not store the quote characters. Populate the fields of the Student structure with the two items from Step 3-1.
The pointers in the pointer array point to random locations in memory and you are trying to use these random addresses. That could certainly explain why the program crashes. Actually there are many ways to crash this program and all steps must be followed carefully to avoid this.
but i have no idea how to fix this or where to begin.
SO isn't really intended for help with your homework.
That being said, the instructions from your teacher are quite elaborate and correct. You'll have to use new Student and new Student[] at one point or another to actually update the Student ** info that is passed to you in order to add that new Student struct you're supposed to add.
I'm guessing Student instances are not allocated before the function is called. You would have to allocate a new instance of Student via new Student and store it into info at index.
info[index] = new Student;

Dynamic Function Memory? C++

I've been reading through some books, and when it comes to Class/Functions using Pointers/Dynamic Memory (or heap or w/e they call it) I start to get confused.
Does anyone have a simple....like easy example they can show, because the books im using are using overly complex examples (large classes or multiple functions) and it makes it hard to follow. Pointers have always been my weak point anyways but I understand BASIC pointers, just classes/functions using them is a little bit confusing.
Also.....when would you use them is another question.
Stack allocation:
char buffer[1000];
Here the 1000 must be a constant. Memory is automatically freed when buffer goes out of scope.
Heap Allocation:
int bufsz = 1000;
char* buffer = new char[bufsz];
//...
delete [] buffer;
Here bufsz can be a variable. Memory must be freed explicitly.
When to use heap:
You don't know how much space you will need at compile time.
You want the memory/object to persist beyond the current scope.
You need a large chunk of memory (stack space is more limited than heap space)
Your computer's RAM is a big pile of bytes ordered one after another, and each one of those bytes can be accesed independently by it's address: an integer number startig from zero, upwards. A pointer is just a variable to hold that address of a single place in memory.
Since the RAM is a big chunk of bytes, the CPU ussually divides that big pile of bytes on several chunks. The most important ones are:
Code
Heap
Stack
The Code chunk is where the Assembly code lies. The Heap is a big pool of bytes used to allocate:
Global variables
Dynamic data, via the new operation on C++, or malloc() on C.
The stack is the chunk of memory that gets used to store:
Local variables
Function parameters
Return values (return statement on C/C++).
The main difference between the Stack and Heap is the way it is used. While the Heap is a big pool of bytes, the Stack "grows" like a stack of dishes: you can't remove the dish on the bottom unless there are no more dishes on it's top.
That's how recursion is implemented: every time you call a function recursively, memory grows on the stack, allocating parameters, local variables and storing return values of the returning functions, one on top of the others just like the stack of dishes.
Data living on the Stack have different "Life Span" than the data living on the Heap. Once a function exits, the data on the local variables get lost.
But if you allocate data on the Heap, that data won't get lost util you explicitly free that data with the delete or free() operations.
A pointer is basically a variable that contains the memory address of another variable (or in other cases to a function, but lets focus on the first).
That means that if I declare int[] x = {5,32,82,45,-7,0,123,8}; that variable will be allocated to memory at a certain address, lets say it got allocated on address 0x00000100 through 0x0000011F however we could have a variable which indicates a certain memory address and we can use that to access it.
So, our array looks like this
Address Contents
0x00000100 1
0x00000104 32
0x00000108 82
0x0000010B 45
0x00000110 -7
0x00000114 0
0x00000118 123
0x0000011B 8
If, for example, we were to create a pointer to the start of the array we could do this: int* p = &x; imagine this pointer variable got created a memory address 0x00000120 that way the memory at that address would contain the memory location for the start of array x.
Address Contents
0x00000120 0x00000100
You could then access the contents at that address through your pointer by dereferencing the pointer so that int y = *p would result in y = 1. We can also move the pointer, if we were to do p += 3; the pointer would be moved 3 addresses forward (note, however, that it moves 3 times the size of the type of object it is pointing to, here I am making examples with a 32 bit system in which an int is 32 bits or 4 bytes long, therefore the address would move by 4 bytes for each increment or 12 bytes in total so the pointer would end up pointing to 0x0000010B), if we were to dereference p again by doing y = *p; then we'd end up having y = 45. This is just the beginning, you can do a lot of things with pointers.
One of the other major uses is to pass a pointer as a parameter to a function so that it can do operations on certain values in memory without having to copy all of them over or make changes that will persist outside of the function's scope.
Warning: Don't do this. This is why we have vectors.
If you wanted to create an array of data, and return if from a function, how would you do it?
Obviously, this does not work:
int [10] makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
You cannot return an array from a function. We can use pointers to refer to the first element of an array, like this:
int * makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return &(arr[0]); // Return the address of the first element.
// Not strictly necessary, but I don't want to confuse.
}
This, however, also fails. arr is a local variable, it goes on the stack. When the function returns, the data is no longer valid, and now you have a pointer pointing to invalid data.
What we need to do is declare an array that will survive even after the function exits. For that, we use keyword new which creates that array, and returns the address to us, which needs to be stored in a pointer.
int * makeArray(int val)
{
int * arr = new int[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
Then you can call that function and use that array like this:
int * a = makeArray(7);
for(int i=0; i<10; ++i)
std::cout << a[i] << std::endl;
delete [] a; // never forget this. Obviously you wouldn't do it right
// away like this, but you need to do it sometime.
Using pointers with new also gives you the advantage that you can determine the size of the array at runtime, something you can't do with local static arrays(though you can in C):
int * makeArray(int size, int val)
{
int * arr = new int[size];
for(int i=0; i<size; ++i)
arr[i] = val;
return arr;
}
That used to be one of the primary purposes for pointers. But like I said at the top, we don't do that anymore. We use vector.
One of the last vestiges of pointers is not for dynamic arrays. The only time I ever use them, is in classes where I want one object to have access to another object, without giving it ownership of that object. So, Object A needs to know about Object B, but even when Object A is gone, that doesn't affect Object B. You can also use references for this, but not if you need to give Object A the option to change which object it has access to.
(not tested, just writing down. and keeping things intentionally primitive, as requested.)
int* oneInt = new int; // allocate
*oneInt = 10; // use: assign a value
cout << *oneInt << endl; // use: retrieve (and print) the value
delete oneInt; // free the memory
now an array of ints:
int* tenInts = new int[10]; // allocate (consecutive) memory for 10 ints
tenInts[0] = 4353; // use: assign a value to the first entry in the array.
tenInts[1] = 5756; // ditto for second entry
//... do more stuff with the ints
delete [] tenInts; // free the memory
now with classes/objects:
MyClass* object = new MyClass(); // allocate memory and call class constructor
object->memberFunction("test"); // call a member function of the object
delete object; // free the object, calling the destructor
Is that what you wanted? I hope it helps.
I think this is what you're asking about:
Basically C++ doesn't allow variable-sized arrays. Any array in C++ has to be given a very specific size. But you can use pointers to work around that. Consider the following code:
int *arry = new int[10];
That just created an array of ints with 10 elements, and is pretty much the same exact thing as this:
int arry[] = int[10];
The only difference is that each one will use a different set of syntax. However imagine trying to do this:
Class class:
{
public:
void initArry(int size);
private:
int arry[];
};
void class::initArry(int size)
{
arry = int[size]; // bad code
}
For whatever reason C++ was designed to not allow regular arrays to be assigned sizes that are determined at runtime. Instead they have to be assigned sizes upon being coded. However the other way to make an array in C++ - using pointers - does not have this problem:
Class class:
{
public:
~class();
void initArry(int size);
private:
int *arry;
};
class::~class()
{
delete []arry;
}
void class::initArry(int size)
{
arry = new int[size]; // good code
}
You have to do some memory cleanup in the second example, hence why I included the destructor, but by using pointers that way you can size the array at runtime (with a variable size). This is called a dynamic array, and it is said that memory here is allocated dynamically. The other kind is a static array.
As far as 2-dimensional arrays go, you can handle it kind of like this:
Class class:
{
public:
~class();
void initArrays(int size1, int size2);
private:
int **arry;
};
class::~class()
{
delete [] arry[0];
delete [] arry[1];
delete [] arry;
}
void class::initArrays(int size1, int size2)
{
arry = new int*[2];
arry[0] = new int[size1];
arry[1] = new int[size2];
}
Disclaimer though: I haven't done much with this language in a while, so I may be slightly incorrect on some of the syntax.

How to delete a pointer after returning its value inside a function

I have this function:
char* ReadBlock(fstream& stream, int size)
{
char* memblock;
memblock = new char[size];
stream.read(memblock, size);
return(memblock);
}
The function is called every time I have to read bytes from a file. I think it allocates new memory every time I use it but how can I free the memory once I have processed the data inside the array? Can I do it from outside the function? Processing data by allocating big blocks gives better performance than allocating and deleting small blocks of data?
Thank you very much for your help!
Dynamic arrays are freed using delete[]:
char* block = ReadBlock(...);
// ... do stuff
delete[] block;
Ideally however you don't use manual memory management here:
std::vector<char> ReadBlock(std::fstream& stream, int size) {
std::vector<char> memblock(size);
stream.read(&memblock[0], size);
return memblock;
}
Just delete[] the return value from this function when you've finished with it. It doesn't matter that you're deleting it from outside. Just don't delete it before you finish using it.
You can call:
char * block = ReadBlock(stream, size);
delete [] block;
But... that's a lot of heap allocation for no gain. Consider taking this approach
char *block = new char[size];
while (...) {
stream.read(block, size);
}
delete [] block;
*Note, if size can be a compile time constant, you can just stack allocate block.
I had a similar question, and produced a simple program to demonstrate why calling delete [] outside a function will still deallocate the memory that was allocated within the function:
#include <iostream>
#include <vector>
using namespace std;
int *allocatememory()
{
int *temppointer = new int[4]{0, 1, 2, 3};
cout << "The location of the pointer temppointer is " << &temppointer << ". Locations pointed to by temppointer:\n";
for (int x = 0; x < 4; x++)
cout << &temppointer[x] << " holds the value " << temppointer[x] << ".\n";
return temppointer;
}
int main()
{
int *mainpointer = allocatememory();
cout << "The location of the pointer mainpointer is " << &mainpointer << ". Locations pointed to by mainpointer:\n";
for (int x = 0; x < 4; x++)
cout << &mainpointer[x] << " holds the value " << mainpointer[x] << ".\n";
delete[] mainpointer;
}
Here was the resulting readout from this program on my terminal:
The location of the pointer temppointer is 0x61fdd0. Locations pointed to by temppointer:
0xfb1f20 holds the value 0.
0xfb1f24 holds the value 1.
0xfb1f28 holds the value 2.
0xfb1f2c holds the value 3.
The location of the pointer mainpointer is 0x61fe10. Locations pointed to by mainpointer:
0xfb1f20 holds the value 0.
0xfb1f24 holds the value 1.
0xfb1f28 holds the value 2.
0xfb1f2c holds the value 3.
This readout demonstrates that although temppointer (created within the allocatememory function) and mainpointer have different values, they point to memory at the same location. This demonstrates why calling delete[] for mainpointer will also deallocate the memory that temppointer had pointed to, as that memory is in the same location.
Yes. You may call delete from outside of the function. In this case though, may I suggest using an std::string so you don't have to worry about the management yourself?
first thing to note: memory allocated with new and delete is completely global. things are not automatically deleted when pointers go out of scope or a function is exited. as long as you have a pointer to the allocation (such as the pointer being returned there) you can delete it when ever and where ever you want. the trick, is just makeing sure other stuff doesn't delete it with out you knowing.
that is a benefit with the sort of function structure the fstream read function has. it is fairly clear that all that function is going to do is read 'size' number of bytes into the buffer you provide, it doesn't matter whether that buffer has been allocated using new, whether its a static or global buffer, or even a local buffer, or even just a pointer to a local struct. and it is also fairly clear that the function is going to do nothing more with the buffer you pass it once it's read the data to it.
on the other hand, take the structure of your ReadBlock function; if you didn't have the code for that it would be tricky to figure out exactly what it was returning. is it returning a pointer to new'd memory? if so is it expecting you to delete it? will it delete it it's self? if so, when? is it even a new pointer? is it just returning an address to some shared static buffer? if so, when will the buffer become invalid (for example, overwritten by something else)
looking at the code to ReadBlock, it is clear that it is returning a pointer to new'd memory, and is expecting you to delete it when ever you are done with it. that buffer will never be overwritten or become invalid until you delete it.
speed wise, thats the other advantage to fsream.read's 'you sort out the buffer' approach: YOU get the choice on when memory is allocated. if you are going "read data, process, delete buffer, read data process delete buffer, ect.... " it is going to be alot more efficient to just allocate one buffer (to the maximum size you will need, this will be the size of your biggest single read) and just use that for everything, as suggested by Stephen.
How about using a static char* memblock; It will be initialised just once and it wont allocate memblock a new space everytime.
Since c++11, one can use std::unique_ptr for this purpose.
From https://en.cppreference.com/book/intro/smart_pointers :
void my_func()
{
int* valuePtr = new int(15);
int x = 45;
// ...
if (x == 45)
return; // here we have a memory leak, valuePtr is not deleted
// ...
delete valuePtr;
}
But,
#include <memory>
void my_func()
{
std::unique_ptr<int> valuePtr(new int(15));
int x = 45;
// ...
if (x == 45)
return; // no memory leak anymore!
// ...
}