Need Help


Write your question here.

There are some problem going on in the definition of allocateData2DbyMalloc() function which block the memory allocation of a 2D array. Can anyone help me please?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#include<cstdlib>
#include <typeinfo>
#include <iostream>
#include <cstring>
using namespace std;

template <class type1, class type2>
type1 allocateData2DbyMalloc(type1 data2D, type2 nRow, type2 nColumn)
{
	int size = 0;
		data2D = (type1)malloc(nRow * sizeof(typeid(**data2D).name()));

		for (int row = 0; row < nRow; row++)
			data2D[row] = (typeid(*data2D).name())malloc(nColumn * sizeof(typeid(**data2D).name()));

	return data2D;
}


int main() {
	int n = 4;
	double** constrainVector;
	constrainVector = nullptr;
	constrainVector = allocateData2DbyMalloc(constrainVector, n, n);
    for(int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
	          constrainVector[i][j] = 6.0;

	return 0;
}
Why on earth are you using malloc?

Anyway, if constrainVector is a double**, to allocate the array of rows of a dynamic 2D array, you'd need to do malloc(sizeof(*data2D) * num_rows);

And then for each inner array, you'd have to do malloc(sizeof(**data2D) * num_columns);
Last edited on
Hi Ganado, thanks for the question. I am using malloc() because at every time step I need to reallocate the memory based on the number of row and column. By the way, malloc(sizeof(*data2D) * num_rows) will return the void pointer, right?. And the I need to cast as type1.
That's not a valid reason to use malloc, in my opinion.

I'm going to skip the usual "use std::vector" lecture and just say:
malloc/free is C
new/delete is C++

So if you must use raw memory management, use new/delete, not malloc/free.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>

int main() {
    
	int rows = 4;
	int columns = 7;
    
	// 
	// Dynamic allocation
	//
	double** constrainVector = new double*[rows]{};
	for (int i = 0; i < columns; i++)
	{
		constrainVector[i] = new double[columns]{};   
	}

	//
	// just filling with numbers to differentiate them
	//
	for(int i = 0; i < rows; i++)
		for (int j = 0; j < columns; j++)
			constrainVector[i][j] = (i+1) * (j+1) % 10; 

	//
	// Display
	//
	for(int i = 0; i < rows; i++)
	{
		for (int j = 0; j < columns; j++)
		{
			std::cout << constrainVector[i][j] << " ";
		}
		std::cout << '\n';
	}
		
	//
	// Clean-up
	//
	for (int i = 0; i < columns; i++)
	{
		delete[] constrainVector[i];
	}
	delete[] constrainVector;

    return 0;
}


By the way, malloc(sizeof(*data2D) * num_rows) will return the void pointer, right?. And the I need to cast as type1.
In C, no casting in needed. (And C purists will protest the unnecessary cast)
In C++, yes you need to cast.
Last edited on
Now, the "use std::vector" lecture.

std::vector lets you resize an array, and takes care of all the dynamic allocation/destruction for you.
No memory leaks possible!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>

int main() {
    
	int rows = 4;
	int columns = 7;
       
	//
	// Dynamic allocation
	//
	std::vector<std::vector<double> > constrainVector(
	    rows, std::vector<double>(columns)
	);

	//
	// just filling with numbers to differentiate them
	//
	for(int i = 0; i < rows; i++)
		for (int j = 0; j < columns; j++)
			constrainVector[i][j] = (i+1) * (j+1) % 10; 

	//
	// Display
	//
	for(int i = 0; i < rows; i++)
	{
		for (int j = 0; j < columns; j++)
		{
			std::cout << constrainVector[i][j] << " ";
		}
		std::cout << '\n';
	}
		
	//
	// No clean-up needed. Great!
	//

	return 0;
}
Last edited on
Thanks a lot bro. Very nice of you. Thanks again.
> There are some problem going on
I see

> I am using malloc() because at every time step I need to reallocate
I'm drinking wax so the nails and bolts don't hurt my stomach

> typeid(*data2D).name()
you wrote type1 data2D, `type1' is the type
by the way, you don't seem to use that parameter
edit: ok, I misread
you could have written type1 **data2D and then use `type1*' for the cast


if you want one contiguous block
1
2
3
4
5
6
7
8
	double** constrainVector = new double*[rows];
	constrainVector[0] = new double[rows*columns]{};
	for (int i = 1; i < rows; i++)
		constrainVector[i] = constrainVector[0]+i*columns;

	//clean up
	delete[] constrainVector[0];
	delete[] constrainVector;
Last edited on
That's pretty clever, it lets you address it with vec[i][j] while still keeping it contiguous. I've always just done my_vec[width * y + x];
I might start using that in my code.
Edit: Err... wait. I can't use that trick with vector without a wrapper class. Ah well, still cool.
Last edited on
there is a way to morph a block to look 2-d without the loop. hang on, Ill look it up.

I think this is one way, hopefully I did this right... and hopefully 'rows' isnt actually columns, Im having concentration issue today.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
   int * i = new int[100];
   for(int x = 0; x < 100; x++)
	   i[x] = x;
   
   typedef  int rows[10]; //making a 10x10 here
   rows* rp = (rows*)(i);
   cout << rp[3][4] << endl; //3rd row, 4th colum... 34 (3*10+4)!
   
    typedef  int rows2[5]; //making a 5x20 here
   rows2* rp2 = (rows2*)(i);
   cout << rp2[3][4]; //3rd row, 4th colum... 19 (3*5+4)
   
     
}


I think you can do the above without the typedefs, using some other pointer & casting magic. The idea is the same, whatever syntax you need to get there

for any beginners, what this does conceptually is make a 1-d array of 1-d arrays, giving a 2-d array. More precisely, deep inside, you create a type that is N units wide, and take a pointer to that. C++'s strongly typed pointers allocate that width for you, so when you cast the big block to a pointer of the wide small type, it slices it for you, moving a full row at a time when you add 1 to that index, because +1 is N units wide.

these tricks can give you some really bad bugs if you mess it up. It yields high performance at high risk.
Last edited on
Topic archived. No new replies allowed.