Malloc a 2D int array in C++ in one expression - c++

Now, I need to save a class to a binary file and the problem I ran into when trying to implement this was that the class had members that were actually pointers, so when writing the class to file it only wrote those pointers, not the actual data that the pointers were pointing to.
So what I did was I used malloc() to allocate memory directly when declaring the members within the class. I know that isn't a good thing to do, but I really need to be able to save this class to a binary file.
I could do this easily with char arrays (1 dimensional), but I also have a single 2D int array, and I just can't figure out how to make it allocate enough memory for both dimensions (I know the dimension sizes beforehand). What should I do?
Maybe there's a way to declare static arrays, since I know their sizes beforehand, and then somehow replace them in memory with new ones? I don't know if I can do that, and I don't want to replace elements one by one.
Note: I need the variables to be pointers, because I want to be able to replace their contents later on, instead of having to replace the elements one by one.

Related

Is it possible to have a std::vector of struct with a fexible array member?

I have a struct with a flexible array member that I need to use.
struct Record
{
uint32_t length;
Data contents[];
};
I'm able to initialize this and use it by doing something like this: (it would also work with malloc or any other dynamic allocation)
vector<Data> members;
vector<uint8_t> buffer;
Record myRecord;
buffer.resize(sizeof(Record) + members.size() * sizeof(Data));
myRecord = *(reinterpret_cast<Record*>(buffer.data());
myRecord.length = static_cast<uint32_t>(members.size());
// copy members to myRecord.contents
That works just fine. But now I need to have an interface that operates on batches of Record, and I have been trying to use an std::vector for this. Then problems start appearing, and I'm guessing it's because std::vector arranges all elements contiguously on memory, and since sizeof(Record) won't take into account the size of the contents (each vector element will hold only 4 bytes, instead of 4 bytes + size_of_contents * sizeof(Data)), the vector elements are actually sharing memory and then each element starts overwriting the contents of the previous element. Does that make sense?
If this really is the problem, I was wondering if there's any way to "force" the vector to allocate a specific size for each element (instead of whatever sizeof returns for the element's type). That way I could make sure that each vector element would have enough size. If that's not possible, is there an alternative solution? Maybe a different container that would allow me to do so? Please keep in mind that I do need to use the struct as it's defined (I would love to just replace the whole thing for a vector but unfortunately that's not possible)
Your principle problem is this:
myRecord = *(reinterpret_cast<Record*>(buffer.data());
That's simply overwriting the data in a stack variable. That does not change the address of myRecord to suddenly point to buffer.data(). Which means when you later do myRecord.contents[...] = ..., you're going to be trashing the stack.
What you almost certainly intended was:
Record *myRecord = (reinterpret_cast<Record*>(buffer.data());
Then you would have a pointer to memory managed by buffer, which would have sufficient storage for the myRecord->contents array.
You cannot treat Record like a value type. As far as C++'s object model is concerned, it's not a value type. It cannot be copied or moved like most C++ types. You can only manipulate it through a pointer/reference to the specific allocation you use here.
That being said, using a vector to manage the storage for your Record* like this is really weird. It'd be better to use a unique_ptr, since resizing the allocation would be a really bad idea.
std::unique_ptr<char[]> storage = new char[sizeof(Record) + (members.size() * sizeof(Data))];
This also prevents the system from initializing the memory, since you're going to overwrite it anyway.
I was wondering if there's any way to "force" the vector to allocate a specific size for each element (instead of whatever sizeof returns for the element's type).
No. vector manages a contiguous array of elements of the same type. And in C++, all objects of the same type have the same size.

C++ dynamic array without STL

This is part of an assignment however I just asking for clarification:
Load data from ATM.txt and store them in a dynamic array (ATM type,
not STL) when the program starts up.
How exactly do I do dynamic arrays without STL? I thought perhaps the assignment means using pointers, the "ATM Type" threw me off.
It's mentioned again:
file accounts.txt into a dynamic array (Account type, not STL)
--not part of Assignment
I've never understood the use of memory unsafe operations, eg pulling the number of items in a file from the first line:
eg.
5
abc
def
hij
kml
mno
Wouldn't it be smarter to use STL (vectors, or C++11 arrays) and not rely on the number in the file as it may not be accurate causing buffer overflows etc?
//Edit
Define a class Account in a file Account.h which contains the data members: customer
id, BSB number, etc.
I assume Account and ATM types are those classes.
The most basic form of dynamic array is one created using new[], and destroyed using delete[]:
ATM * atms = new ATM[count];
// do stuff with the array
delete [] atms;
However, this brings the danger that the code using the array might throw an exception, return from the function, or otherwise prevent the delete[] from happening. If that happens, then you will lose the only pointer to the allocated memory, and it will remain allocated but inaccessible; this is known as a memory leak. For this reason, it's better to wrap the array in a class, with:
member variables to store a pointer to the array, and (optionally) its size
constructors and/or functions to allocate the array
a destructor to delete the array
(optionally) function(s) to resize the array
Deleting the allocation in an object's destructor uses the principle of RAII to ensure that the array is deleted once it is no longer needed.
This leaves one more danger: if you copy this array object, then you will end up with two objects that both try to delete the same array, which is disasterous. To prevent this, you'll need to consider the Rule of Three. Either write a copy constructor and copy-assignment operator to allocate a new array and copy the contents; or delete them. (If you're learning old-fashioned C++, then you can't delete member functions, so you'll have to declare them private and not implement them instead).
Wouldn't it be smarter to use STL?
Usually, yes. But if you're learning C++, it's a good idea to understand how memory management works, as well as how to get the library to handle it for you. That's probably part of the point of this exercise.
A common approach for this kind of assignment would be to simulate the auto-expanding behavior of a vector on your own. Allocate an array for your data on the heap, and keep track of its length and the number of items you've stored in the array.
Once you've filled the array with your data, expand the maximum size by some amount and allocate a new array. This allows you to copy the data from the old array into the new array, and then continue adding items until you run out of space again.
Basically if you need to implement a dynamic array without using STL, you have to deal explicitely with memory allocation/deallocation.
Basically you have to:
Allocate space with malloc the first time array is constructed or used
Keep track of inserted/removed elements
Use realloc when you have finished the allocated space
Free the allocated space when the array is destroyed
Of course implementing a good STL like container like std::vector isn't an easy task (eventually a nice homework!).
What I can suggest is the following:
Avoid as much as possible reallocation. When the space is finished, allocate some more space in order to avoid to continuosly call realloc (see std::vector::reserve)
Avoid to realloc space when elements are removed. Once you have allocated, unless memory usage is too high, let the allocated space as is, in order to avoid future reallocation.
Wouldn't it be smarter to use STL (vectors, or C++11 arrays) and not
rely on the number in the file as it may not be accurate causing
buffer overflows etc?
The internals of std::vector aren't magic. It's possible to manually do yourself what std::vector does for you.
It sounds like that's what you're supposed to do for this assignment; make your own 'ATM type' that can manage reading data safely from the ATM.txt file, and an 'Account type' that can hold data from the accounts.txt file. You should probably get some clarification from whomever wrote the assignment on how exactly they expect these types to be designed/used. Also looking back at whatever class materials you have should tell you what you need to know in terms of using dynamic arrays.
Since this is homework we don't want to give answers directly, but in general what I suggest is:
Make a class myDynamicArray
Make the class contain an int or long to store array size
Allocate memory for your array using "new". From the assignment, it looks like it might be an array of strings or, if the professor is strictly banning STL (string is now considered STL), it will be an array of character arrays.
Write an insert method which, before inserting, checks the size (see #2) of your array and, if it isn't large enough, makes it bigger. One way to do this without using pre-C++ functions, which I assume is best since this is a C++ class, is to allocate a new array of larger size --> copy data from old array --> Insert any new data. How much larger? You might pick, say, 20% larger with each new allocation. Microsoft's C# allocates "the next largest prime number" of elements, though they have really fast memory allocation routines.
Don't forget to delete() the dynamic array when finished with it (what "finished" means depends on the assignment). Note that once the program exits, technically the memory should be freed up automatically, but it's very bad practice to not free it up yourself (think larger, non-academic programs that aren't regularly shut down).
I'd avoid the template code another user provided. I'm sure it's great code, but it's going to raise an eyebrow to use something that advanced in an early C++ class.
Suggested reading:
http://www.cplusplus.com/doc/tutorial/dynamic/

multidimensional array of vectors pointing to class objects c++

I'm not exactly sure what's happening as I am relatively new to c++
I have globally defined the following above my main loop
vector<Character*> monsters[2][3][6];
vector<Item*> loot[2][3][6];
vector<NPC*> npc[2][3][6];
vector<Objects*> objects[2][3][6];
Inside my Character.h file I have also defined the objects array
extern vector<Objects*> objects[2][3][6];
Everything was working fine until I created the objects array.
It appears that if I add more than 8 objects to the monsters array strange values start appearing into objects and the size of objects increases.
My code is a mess and I'm not sure exactly what I should include here. I hope this is enough to give you an idea of what I'm on about.
I haven't tested this thoroughly so it may very well happen to all of my arrays...
It appears that the monsters array was not large enough so it was "overflowing" and placing objects outside of the array, thus ending up within another array.
Apologies for inconvenience. I hope this helps someone.
Ultimately you want to write your own small Grid class that fits your need or use Boost.MultiArray to handle such cases. Working with nested raw arrays leads to a mess in the long run. Maybe you also want to avoid storing pointers and store objects by value.

How to use a std::vector in a C function

A C function expects an array of buffers to be in scope at runtime. e.g.
char values[x][y]
The C function will populate the buffers
I would like to use a dynamic array so I don't have to hard code the dimensions
How do I use a std::vector in this situation?
Just to be clear, I am using C++. The C function is contained in a library that I cannot modify.
If you just want to pass the dynamic array encapsulated in a std::vector to a c routine you can pass a pointer to the head of the underlying array as:
std::vector<char> myvector;
// size-up myvector as needed
foo(&myvector[0]); // pass a pointer to start of myvector to function foo
The c++ standard ensures that the underlying array in std::vector is always contiguous.
Hope this helps.
EDIT: While the declaration char values[x][y] creates an "array of arrays" the memory for values will actually just be a contiguous block, essentially char linear_values[x * y].
If you size your std::vector to include a count of x * y elements it should give you the same underlying dynamically allocated array space.
The c function will access the array in row-major order, so the first row of elements will come first, followed by the second full row etc...
C doesn't have standard data structures libraries.
If you really want all the functionality of a vector, and it's not for something critical, you can probably find someone's pet implementation of a straight C vector online and just use that.
If it is critical, write your own. It's not too hard, and can be quite useful.
If you just want a dynamically growing array, it's easy to emulate that behavior of a vector using the realloc function, which extends the dimensions of a heap-allocated array. Start with a small array, and grow as needed when you reach the end. It's more efficient to grow in big chunks, but if you have some idea of what your data looks like you could grow it in a different way. A common method is doubling the array size every time you run out.
You can get the details of realloc at:
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
or, on a *nix system:
man realloc
You can't.
By definition, C knows nothing of any of the required components of a std::vector, including, but not limited to:
C does not have namespaces, so it can't understand the std namespace.
C does not have templates, so it can't understand the std::vector<T> type.
Essentially, you need what looks like a C function, but that is, for all intents and purposes, a C++ function.
The simplest way to achieve this is probably to write what looks like a C function, using C++, and running the whole mess through a C++ compiler rather than a C compiler.

Why "delete [][]... multiDimensionalArray;" operator in C++ does not exist

I was always wondering if there is operator for deleting multi dimensional arrays in the standard C++ language.
If we have created a pointer to a single dimensional array
int *array = new int[size];
the delete looks like:
delete [] array;
That's great. But if we have two dimension array, we can not do
delete [][] twoDimenstionalArray;
Instead, we should loop and delete the items, like in this example.
Can anybody explain why?
Technically, there aren't two dimensional arrays in C++. What you're using as a two dimensional array is a one dimensional array with each element being a one dimensional array. Since it doesn't technically exist, C++ can't delete it.
Because there is no way to call
int **array = new int[dim1][dim2];
All news/deletes must be balanced, so there's no point to a delete [][] operator.
new int[dim1][dim2] returns a pointer to an array of size dim1 of type int[dim2]. So dim2 must be a compile time constant. This is similar to allocating multi-dimensional arrays on the stack.
The reason delete is called multiple times in that example is because new is called multiple times too. Delete must be called for each new.
For example if I allocate 1,000,000 bytes of memory I cannot later delete the entries from 200,000 - 300,00, it was allocated as one whole chunk and must be freed as one whole chunk.
The reason you have to loop, like in the example you mention, is that the number of arrays that needs to be deleted is not known to the compiler / allocator.
When you allocated your two-dimensional array, you really created N one-dimensional arrays. Now each of those have to be deleted, but the system does not know how many of them there are. The size of the top-level array, i.e. the array of pointers to your second-level arrays, is just like any other array in C: its size is not stored by the system.
Therefore, there is no way to implement delete [][] as you describe (without changing the language significantly).
not sure of the exact reason from a language design perspective, I' guessing it has something to do with that fact that when allocating memory you are creating an array of arrays and each one needs to be deleted.
int ** mArr = new int*[10];
for(int i=0;i<10;i++)
{
mArr[i]=new int[10];
}
my c++ is rusty, I'm not sure if thats syntactically correct, but I think its close.
While all these answers are relevant, I will try to explain what came to an expectation, that something like delete[][] array; may work on dynamically allocated arrays and why it's not possible:
The syntax int array[ROWS][COLS]; allowed on statically allocated arrays is just abstraction for programmers, which in reality creates one-dimensional array int array[ROWS*COLS];. But during compilation process (when dimension sizes COLS and ROWS must be constants by standard) the compiler also remembers the size of those dimensions, that are necessary to later address elements using syntax e.g. array[x][y] = 45. Compiler, being known of this size, will then replace [x][y] with the corresponding index to one-dimensional array using simple math: [COLS*x + y].
On the other hand, this is not the case with dynamically allocated arrays, if you want the same multi-dimensional functionality (in fact notation). As their size can be determined during runtime, they would have to remember the size of each additional dimension for later usage as well - and remember that for the whole life of the array. Moreover, system changes would have to be implemented here to work with arrays actually as multi-dimensional, leaving the form of [x][y] access notation in the code, not replacing it with an one-dimensional notation during compilation, but later replacing it within runtime.
Therefore an absence of array = new int[ROWS][COLS] implies no necessity for delete[][] array;. And as already mentioned, it can't be used on your example to delete your "multi-dimensional" array, because your sub-arrays (additional dimensions) are allocated separately (using separate new call), so they are independent of the top array (array_2D) which contains them and they all can't be deleted at once.
delete[] applies to any non-scalar (array).
You can use a wrapper class to do all those things for you.
Working with "primitive" data types usually is not a good solution (the arrays should be encapsulated in a class). For example std::vector is a very good example that does this.
Delete should be called exactly how many times new is called. Because you cannot call "a = new X[a][b]" you cannot also call "delete [][]a".
Technically it's a good design decision preventing the appearance of weird initialization of an entire n-dimensional matrix.
Well, I think it is easy to implement, but too dangerous. It is easy to tell whether a pointer is created by new[], but hard to tell about new[]...[](if allowed).