I have to create a matrix with the width and height determined by two parameters obtained from the writing of a file. But, in some cases when the matrix is too big, I've got a segmentation fault. I think is probably because I'm creating the matrix in a static way, so I need to create it dynamically, but is here where my problem appears, because I don't know how to do it.
My code right now is this:
FILE * fp;
unsigned int width=0;
unsigned int height=0;
//Open the file. argv[4] parameter contains the file
fp=fopen (argv[4],"r");
//Go to the last position which indicates the size
fseek(fp, 0, SEEK_END);
//Return to the start:
rewind(fp);
//The value of the first 4 bytes represent the width
size_t return1 = fread(&width,4,1,fp);
//The value of the next 4 bytes represent the height
size_t return2 = fread(&height,4,1,fp);
//Matrix creation
if (return1 > 0 && return2 > 0) {
unsigned int matrix[width][height];
If you are having trouble figuring out how to create arrays dynamically, I would definitely advise you to use the vector class instead.
Vectors are dynamically allocated, and can scale.
std::vector<unsigned int> matrix{width * height};
Notice that I made the vector a single dimension, since it really simplifies a lot when allocating the vector.
To access a specific coordinate you could use:
matrix.at(w * width + h);
Where w and h are the coordinates, h should obviously be in the range 0 <= h < height.
If you were to dynamically allocate your array you would have to use the new operator, and then have to remember to clean up afterwards as well using the proper delete[] operator. There is a better answer for that here on Stack Overflow: How do I declare a 2d array in C++ using new?
Basically it would boil down to:
unsigned int** matrix = new unsigned int*[width];
for (int w = 0; w < width; ++w) {
matrix[w] = new unsigned int[height];
}
Then you would have to remember to delete the matrix again, using something like this:
for (int w = 0; w < width; ++w) {
delete [] matrix[w];
}
delete [] matrix;
So, in other words, I recommend that you use the vector class instead.
Of course with sufficiently large values of width and height, even vector can fail, simply because you are trying to allocate too much memory. If that is the case I think you should revisit your design, and reconsider how it is made.
Remember to include the vector header when using vectors:
#include <vector>
unsigned int matrix[width][height];
This has two problems.
Firstly, width and height are not compile time constants, which is required by the C++ standard for the size of the array. Therefore your program is ill-formed. Your compiler might support variable length arrays (VLA) as a language extension, so it might work with your compiler anyway.
Secondly, VLA may be stored on the stack, and stack space is limited. Indeed, with a large array you can easily overflow the stack. You are correct, that you'll need to allocate the array dynamically. Both because the size is dynamic (assuming you want your program to work with other, standard compliant compilers that do not support VLA) and because it prevents the stack from overflowing.
The simplest way to create a dynamic array is std::vector. Tommy Andersen goes more into depth on how to use vectors in his answer.
Related
I've got some data structured as a multi-dimensional array, i.e. double[][], and I need to pass it to a function that expects a single linear array of double[] along with dimensional metadata for the multi-dimensional representation.
For example, I might have a 3 x 5 multidimensional array, which I need to pass as a 15-element flat array along with height and width parameters so that the function knows it is a 3x5 array rather than a 5x3 array.
The function will then return a flat array and size metadata, which I need to use to convert the data back into a multidimensional type.
I believe the data layout in memory is exactly the same for both the flat and multi-dimensional representations; the only difference is how the indexing operations are performed. So I'd like to do the "conversion" with typecasting rather than copying the array values.
What's the most correct and readable way to typecast between multidimensional and flat arrays of the same total size?
I actually know what the dimensions of the multi-dimensional array will be at compile time. The array sizes aren't dynamic.
The most correct way has been given by #Maxim Egorushkin and #ypnos: double *flat = &multi[0][0];. And it will work fine with any decent compiler. But unfortunately is not valid C++ code and invokes Undefined Bahaviour.
The problem is that for an array double multi[N][M]; (N and M being compile time contant expressions), &multi[0][0] is the address of the first element of an array of size M. So it is legal to do pointer arithmetics only up to M. See this other question of mine for more details.
What's the most correct and readable way to typecast between multidimensional and flat arrays of the same total size?
The address of the first array element coincides with the address of the array. You can pass around the address of the first element, no casting is necessary.
I would assume the most popular way to do it is:
double *flat = &multi[0][0];
This is how it is done in C, and you do operate with simple C arrays.
You could also have a look at std::array in your use case (dimensions known at compile time), but that one is not multi-dimensional, so if you would cascade it, you would lose the contiguous layout.
You can use cast to a reference to an array. This require to use some fancy C++ type syntax but in return it allows to use all features that work on arrays, like for each loop.
#include <iostream>
using namespace std;
int main()
{
static constexpr size_t x = 5, y = 3;
unsigned multiArray[x][y];
for (size_t i = 0; i != x; ++i)
for (size_t j = 0; j != y; ++j)
multiArray[i][j] = i * j;
static constexpr size_t z = x * y;
unsigned (&singleArray)[z] = (unsigned (&)[z])multiArray[0][0];
for (const unsigned value : singleArray)
cout << value << ' ';
cout << endl;
return 0;
}
Take into account that this and other methods basing on casts work only with real multi-dimensional arrays. If it is an array of arrays (like unsigned **multiArray;), it isn't allocated in a continuous block of memory and a cast cannot bypass that.
I have got a class that represents a 2D map with size 40x40.
I read some data from sensors and create this map with marking cells if my sensors found something and I set value of propablity of finding an obstacle. For example when I am find some obstacle in cell [52,22] I add to its value for example to 10 and add to surrounded cells value 5.
So each cell of this map should keep some little value(propably not bigger). So when a cell is marked three times by sensor, its value will be 30 and surronding cells will have 15.
And my question is, is it worth to use casual array or is it better to use vector even I do not sort this cells, dont remove them etc. I just set its value, and read it later?
Update:
Actually I have in my header file:
using cell = uint8_t;
class Grid {
private:
int xSize, ySize;
cell *cells;
public:
//some methods
}
In cpp :
using cell = uint8_t;
Grid::Grid(int xSize, int ySize) : xSize(xSize), ySize(ySize) {
cells = new cell[xSize * ySize];
for (int i = 0; i < xSize; i++) {
for (int j = 0; j < ySize; j++)
cells[x + y * xSize] = 0;
}
}
Grid::~Grid(void) {
delete cells;
}
inline cell* Grid::getCell(int x, int y) const{
return &cells[x + y * xSize];
}
Does it look fine?
I'd use std::array rather than std::vector.
For fixed size arrays you get the benefits of STL containers with the performance of 'naked' arrays.
http://en.cppreference.com/w/cpp/container/array
A static (C-style) array is possible in your case since the size in known at compile-time.
BUT. It may be interesting to have the data on the heap instead of the stack.
If the array is a global variable, it's ugly an bug-prone (avoid that when you can).
If the array is a local variable (let say, in your main() function), then a stack overflow may occur. Well, it's very unlikely for a 40*40 array of tiny things, but I'd prefer have my data on the heap, to keep things safe, clean, and future-proof.
So, IMHO you should definitely go for the vector, it's fast, clean and readable, and you don't have to worry about stack overflow, memory allocation, etc.
About your data. If you know your values are storable on a single byte, go for it !
An uint8_t (same as unsigned char) can store values from 0 to 255. If it's enough, use it.
using cell = uint8_t; // define a nice name for your data type
std::vector<cell> myMap;
size_t size = 40;
myMap.reserve(size*size);
side note: don't use new[]. Well, you can, but it has no advantages over a vector. You will probably only gain headaches handling memory manually.
Some advantages of using a std::vector is that it can be dynamically allocated (flexible size, can be resized during execution, etc) and can be passed/returned from a function. Since you have a fixed size 40x40 and you know you have one element int in every cell, I don't think it matters that much in your case and I would NOT suggest using a class object std::vector to process this simple task.
And here is a possible duplicate.
So I'm trying to create an n-dimensional array structure for use in a maze generating program.
I've simplified my problem (for the purposes of trying to get the theory figured out before making it templatized and adding all the necessary helper functions)
So my problem currently boils down to wanting to make an ArbitraryArray class that takes in an argument to its constructor specifying the number of dimensions. Each dimension will have length = 5. (for now)
This is what I have so far:
class ArbitraryArray{
public:
int array[5];
ArbitraryArray*subArray;
ArbitraryArray(){}
ArbitraryArray(int depth){
if (depth == 2) subArray = new ArbitraryArray[5];
else if (depth > 2) for (int i = 0; i < 5; i++) subArray = new ArbitraryArray(depth - 1);
}
};
And I'd create a 2 dimensional object like so:
ArbitraryArray testArray(2);
Or a 3 dimensional object like so:
ArbitraryArray testArray(3);
Problem is, when I tested it for depth = 3 and then tried to set an integer value, via:
testArray.subArray[3].subArray[4].array[4] = 7;
I received a runtime error, leading me to believe that I'm doing something wrong in how I allocate these objects dynamically.
Also, I included an empty default constructor since that gets called by lines like:
subArray = new ArbitraryArray[5];
I'm aware this may not be the best way to go about creating an arbitrary dimensional array data structure, but I'd really like to figure out why this implementation is not working before potentially looking for better methods.
Also I am aware I shouldn't have a line like:
int array[5];
And that it should be a pointer instead so that there isn't a ton of wasted memory allocation for all the levels of the array above the bottom dimension. And I intend to modify it to that after I get this basic idea working.
How about using std::vector for allocating the correct amount of blank memory, which would be
sizeof(T) * dim1 * dim2 * dim3 * ...
Then write a helper class which takes care of the indexing, i.e., it will compute i from given (x,y,z,...), whatever many dimensions you might have.
The beauty of this approach, IMHO, lies in not having to fiddle with pointers, and the helper class simply implements an indexing scheme of your preference (row major or column major).
EDIT
When using std::valarray, things may become easier, as you can use std::slice and/or std::gslice to calculate your indexing for you.
Haven't compiled anything, just visual inspection. What about this:
template<int array_length>
class ArbitraryArray{
public:
int array[array_length];
ArbitraryArray ** subArray;
ArbitraryArray(){}
ArbitraryArray(int depth){
if (depth == 1)
subArray = 0;
else {
subArray = new ArbitraryArray*[array_length];
for (int i = 0; i < array_length; i++)
subArray[i] = new ArbitraryArray(depth - 1);
}
}
};
Well, for once, if depth is greater than 2, you create five ArbitraryArrays, but you save all their pointers in one SubArray pointer. SubArray needs to be an array of pointers to ArbitraryArrays, try ArbitraryArray *subArray[5]; and for (int i = 0; i < 5; i++) subArray[i] = new ArbitraryArray(depth - 1) and see what happens.
In your example you are creating an array that is all over the place in memory instead of one array that is stored in a continuous block of memory. This could cause some issues depending on you handle the memory. e.g. using memcpy on it will never work.
I think a little more flexible approach would be create one large array and instead have an index into the array based on the number of dimensions
int n = static_cast<int>(pow( 5.0, static_cast<double>(depth) ));
Type* a = new Type[ n ];
i.e. since you base your array size on 5, a 2-dim size would be 5x5 and a 3-dim 5x5x5
to access an element in the array say a[2,2,3] (0-based) it could be calculated as
a[2*5*5 + 2*5 + 3]
Just use the Boost multi_array class. It is very flexible, efficient and can perform bounds checking.
Boost Multi-Array
I have a for-loop that needs to incrementally add columns to a matrix. The size of the rows is known before entering the for-loop, but the size of the columns varies depending on some condition. Following code illustrates the situation:
N = getFeatureVectorSize();
float **fmat; // N rows, dynamic number of cols
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
float *fv = new float[N];
getObjectFeatureVector(fv);
// How to add fv to fmat?
}
}
Edit 1 This is how I temporary solved my problem:
N = getFeatureVectorSize();
float *fv = new float[N];
float *fmat = NULL;
int col_counter = 0;
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
getObjectFeatureVector(fv);
fmat = (float *) realloc(fmat, (col_counter+1)*N*sizeof(float));
for(int r=0; r<N; r++) fmat[col_counter*N+r] = fv[r];
col_counter++;
}
}
delete [] fv;
free(fmat);
However, I'm still looking for a way to incrementally allocate memory of a two-dimensional array in C/C++.
To answer your original question
// How to add fv to fmat?
When you use float **fmat you are declaring a pointer to [an array of] pointers. Therefore you have to allocate (and free!) that array before you can use it. Think of it as the row pointer holder:
float **fmat = new float*[N];
Then in your loop you simply do
fmat[i] = fv;
However I suggest you look at the std::vector approach since it won't be significantly slower and will spare you from all those new and delete.
better - use boost::MultiArray as in the top answer here :
How do I best handle dynamic multi-dimensional arrays in C/C++?
trying to dynamically allocate your own matrix type is pain you do not need.
Alternatively - as a low-tech, quick and dirty solution, use a vector of vectors, like this :
C++ vector of vectors
If you want to do this without fancy data structures, you should declare fmat as an array of size N of pointers. For each column, you'll probably have to just guess at a reasonable size to start with. Dynamically allocate an array of that size of floats, and set the appropriate element of fmat to point at that array. If you run out of space (as in, there are more floats to be added to that column), try allocating a new array of twice the previous size. Change the appropriate element of fmat to point to the new array and deallocate the old one.
This technique is a bit ugly and can cause many allocations/deallocations if your predictions aren't good, but I've used it before. If you need dynamic array expansion without using someone else's data structures, this is about as good as you can get.
To elaborate the std::vector approach, this is how it would look like:
// initialize
N = getFeatureVectorSize();
vector<vector<float>> fmat(N);
Now the loop looks the same, you access the rows by saying fmat[i], however there is no pointer to a float. You simply call fmat[i].resize(row_len) to set the size and then assign to it using fmat[i][z] = 1.23.
In your solution I suggest you make getObjectFeatureVector return a vector<float>, so you can just say fmat[i] = getObjectFeatureVector();. Thanks to the C++11 move constructors this will be just as fast as assigning the pointers. Also this solution will solve the problem of getObjectFeatureVector not knowing the size of the array.
Edit: As I understand you don't know the number of columns. No problem:
deque<vector<float>> fmat();
Given this function:
std::vector<float> getObjectFeatureVector();
This is how you add another column:
fmat.push_back(getObjectFeatureVector());
The number of columns is fmat.size() and the number of rows in a column is fmat[i].size().
I need to create a large two dimensional array of objects. I've read some related questions on this site and others regarding multi_array, matrix, vector, etc, but haven't been able to put it together. If you recommend using one of those, please go ahead and translate the code below.
Some considerations:
The array is somewhat large (1300 x 1372).
I might be working with more than one of these at a time.
I'll have to pass it to a function at some point.
Speed is a large factor.
The two approaches that I thought of were:
Pixel pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i][j].setOn(true);
...
}
}
and
Pixel* pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i][j] = new Pixel();
pixelArray[i][j]->setOn(true);
...
}
}
What's the right approach/syntax here?
Edit:
Several answers have assumed Pixel is small - I left out details about Pixel for convenience, but it's not small/trivial. It has ~20 data members and ~16 member functions.
Your first approach allocates everything on stack, which is otherwise fine, but leads to stack overflow when you try to allocate too much stack. The limit is usually around 8 megabytes on modern OSes, so that allocating arrays of 1300 * 1372 elements on stack is not an option.
Your second approach allocates 1300 * 1372 elements on heap, which is a tremendous load for the allocator, which holds multiple linked lists to chunks of allocted and free memory. Also a bad idea, especially since Pixel seems to be rather small.
What I would do is this:
Pixel* pixelArray = new Pixel[1300 * 1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i * 1372 + j].setOn(true);
...
}
}
This way you allocate one large chunk of memory on heap. Stack is happy and so is the heap allocator.
If you want to pass it to a function, I'd vote against using simple arrays. Consider:
void doWork(Pixel array[][]);
This does not contain any size information. You could pass the size info via separate arguments, but I'd rather use something like std::vector<Pixel>. Of course, this requires that you define an addressing convention (row-major or column-major).
An alternative is std::vector<std::vector<Pixel> >, where each level of vectors is one array dimension. Advantage: The double subscript like in pixelArray[x][y] works, but the creation of such a structure is tedious, copying is more expensive because it happens per contained vector instance instead of with a simple memcpy, and the vectors contained in the top-level vector must not necessarily have the same size.
These are basically your options using the Standard Library. The right solution would be something like std::vector with two dimensions. Numerical libraries and image manipulation libraries come to mind, but matrix and image classes are most likely limited to primitive data types in their elements.
EDIT: Forgot to make it clear that everything above is only arguments. In the end, your personal taste and the context will have to be taken into account. If you're on your own in the project, vector plus defined and documented addressing convention should be good enough. But if you're in a team, and it's likely that someone will disregard the documented convention, the cascaded vector-in-vector structure is probably better because the tedious parts can be implemented by helper functions.
I'm not sure how complicated your Pixel data type is, but maybe something like this will work for you?:
std::fill(array, array+100, 42); // sets every value in the array to 42
Reference:
Initialization of a normal array with one default value
Check out Boost's Generic Image Library.
gray8_image_t pixelArray;
pixelArray.recreate(1300,1372);
for(gray8_image_t::iterator pIt = pixelArray.begin(); pIt != pixelArray.end(); pIt++) {
*pIt = 1;
}
My personal peference would be to use std::vector
typedef std::vector<Pixel> PixelRow;
typedef std::vector<PixelRow> PixelMatrix;
PixelMatrix pixelArray(1300, PixelRow(1372, Pixel(true)));
// ^^^^ ^^^^ ^^^^^^^^^^^
// Size 1 Size 2 default Value
While I wouldn't necessarily make this a struct, this demonstrates how I would approach storing and accessing the data. If Pixel is rather large, you may want to use a std::deque instead.
struct Pixel2D {
Pixel2D (size_t rsz_, size_t csz_) : data(rsz_*csz_), rsz(rsz_), csz(csz_) {
for (size_t r = 0; r < rsz; r++)
for (size_t c = 0; c < csz; c++)
at(r, c).setOn(true);
}
Pixel &at(size_t row, size_t col) {return data.at(row*csz+col);}
std::vector<Pixel> data;
size_t rsz;
size_t csz;
};