Reallocation of contiguous 2D array - c

I am generating contiguous 2d arrays using the method posted on here by Shawn Chin.[1][2] It works very well.
Briefly from his post:
char** allocate2Dchar(int count_x, int count_y) {
int i;
# allocate space for actual data
char *data = malloc(sizeof(char) * count_x * count_y);
# create array or pointers to first elem in each 2D row
char **ptr_array = malloc(sizeof(char*) * count_x);
for (i = 0; i < count_x; i++) {
ptr_array[i] = data + (i*count_y);
}
return ptr_array;
}
And the following free function:
void free2Dchar(char** ptr_array) {
if (!ptr_array) return;
if (ptr_array[0]) free(ptr_array[0]);
free(ptr_array);
}
It is not obvious to me how to create an equivalent reallocate function in either dimension, though I am only interested in realloc'ing the number of rows while maintaining continuity. Growing the number of columns would be interesting to understand but probably quite difficult. I haven't found any direct discussion of this issue anywhere other than to say, "it's hard!".[2]
Of course this is doable by a horrible brute force method, copying the data to a new 1D array (data, above) for storage, realloc'ing the 1D array, then freeing and regenerating the pointers (ptr_array) to the row elements for the new size. This, however, is pretty slow for row modifications, since it is necessary to at least double the memory requirement to copy out the data, and this is truly horribly bad for changing the number of columns.
This is an example of said method for changing the number of rows (it wouldn't work properly for changing the number of columns because the offsets for the pointers would be wrong for the data). I haven't fully tested this, but you get the idea ...
double **
reallocate_double_array (double **ptr_array, int count_row_old, int count_row_new, int count_col)
{
int i;
int old_size = count_row_old * count_col;
int new_size = count_row_new * count_col;
double *data = malloc (old_size * sizeof (double));
memcpy (&data[0], &ptr_array[0][0], old_size * sizeof (double));
data = realloc (data, new_size * sizeof (double));
free (ptr_array[0]);
free (ptr_array);
ptr_array = malloc (count_row_new, sizeof (double *));
for (i = 0; i < count_row_new; i++)
ptr_array[i] = data + (i * count_col);
return ptr_array;
}
Plus, this method requires you know the previous size, which is obnoxious!
Any thoughts greatly appreciated.
[1] How can I allocate a 2D array using double pointers?
[2] http://www.eng.cam.ac.uk/help/tpl/languages/C/teaching_C/node52.html

The first malloc and the memcpy are unnecessary, because you have easy access to the original data array at ptr_array[0]. You don't need to know the old size, because realloc should recall how much it allocated at the address and move the correct ammount of data.
Something like this should work.
double **
reallocate_double_array (double **ptr_array, int count_row_new, int count_col)
{
int i;
int new_size = count_row_new * count_col;
double *data = ptr_array[0];
data = realloc (data, new_size * sizeof (double));
free (ptr_array);
ptr_array = calloc (count_row_new, sizeof (double *));
for (i = 0; i < count_row_new; i++)
ptr_array[i] = data + (i * count_col);
return ptr_array;
}

Related

Changing size of Dynamically allocating arrays

In C++, we can change size of dynamically allocating arrays easily with std::vector. So I wondered if there is any way to change size of dynamically allocating arrays in C without using any other arrays or dynamically allocating arrays and delete the first one?
I have tried in using with arrays to copy the first one then deleting data which I don't want to use. Now I am hoping to use in another brainly way.
Like some people have suggested in the comments, any memory block allocated with malloc can be resized with realloc. Its internal logic will do the copying for you, if necessary. Note that realloc returns a NULL pointer if the resizing fails, so code like this will risk you a memory leak:
int data_length = 5;
int *data = malloc(data_length * sizeof(int));
...
data = realloc(data, data_length * 2 * sizeof(int));
You should instead do something like this:
int data_length = 5;
int *data = malloc(data_length * sizeof(int));
...
int new_data_length = data_length * 2;
int *new_data = realloc(data, new_data_length * sizeof(int));
if (new_data) {
data_length = new_data_length;
data = new_data;
}
Do the same when decreasing the size.

How to use realloc in a double pointer array?

int row = 5, col =5 ;
arr = (int **) malloc(sizeof(int*) * row);
for (int index=0; index<row; index++)
{
*(arr + index) = (int *) malloc(sizeof(int) * col);
}
I using this code to declare a double pointer array. How to use realloc to increase both the rows and columns, if needed ?
We don't know the number of inputs we are going to get :
void increase(int** arr)
{
*arr = (int *) realloc(*arr, 5 * sizeof (int));
}
I don't think that it's working. I need to reallocate both rows and columns.
I inserted the condition:
if(var % 5 == 4)
then call the function increase and reallocate but it doesn't seems to be working.
To make your code reusable for different data-type in C (int/double). You need to use the concept of generic data-type.
To use generic data-type, it might require you to implement data-type specific custom free function. For int and double you do not need to use custom specific free function; but free is not trivial if you are new to C.
To grow your data-structure, you need to define a function which grows the data-structure. Check this stack implementation from Stanford (Lecture: [4, 8)) https://www.youtube.com/playlist?list=PL9D558D49CA734A02
One advice.
Do not re-cast the output of malloc(). Not required!
Change:
arr = (int **) malloc(sizeof(int*) * row);
To:
arr = malloc(sizeof(int*) * row);
I am getting an error main.cpp…
Don't use the file name suffix .cpp for C programs - .cpp may cause gcc to compile the source code for another language.
I need to reallocate both rows and columns.
Since you don't pass dimensions to your increase() function, you apparently want it to increase the number of both rows and columns by 5. Since you used realloc(*arr, 5 * sizeof (int)), you apparently overlooked that the size passed to realloc() is not an increment, but rather the total size of the new memory space. Also, you should account for the possibility that the reallocation in increase() fails, and allow it to return an error indication. The following example returns the new (maybe moved) pointer or NULL in case of failure. As a bonus, this increase() function can also be used for the initial creation.
int row, col;
#include <malloc.h>
int **increase(int **arr)
{ // enlarge the "matrix" by 5 rows and 5 columns
int rownew = row+5, colnew = col+5;
arr = realloc(arr, rownew * sizeof *arr); // increase the rows
if (!arr) return NULL; // realloc error
do arr[row++] = NULL; while (row < rownew); // initialize new row pointers
for (rownew = 0; rownew < row; ++rownew)
{ // increase the columns in each row
int *newptr = realloc(arr[rownew], colnew * sizeof *newptr);
if (!newptr) return NULL; // realloc error
arr[rownew] = newptr;
}
col = colnew;
return arr;
}
main()
{
int **arr = increase(NULL); // create initial 5x5 "matrix"
int **newarr = increase(arr); // enlarge to new 10x10 "matrix"
if (newarr) arr = newarr;
else /* realloc error handling */;
}
Note that in something other than that toy example, we'd probably pass the dimensions as parameters rather than as globals.

C Dynamic allocation speed question

I'm using this code to dynamically create a 2d array:
char **FileTables;
int rows = 1000;
int i;
FileTables = (char**)malloc(rows * sizeof(char));
for (i = 0; i < rows; i++) {
FileTables[i] = (char*)malloc(256 * sizeof(char));
}
Problem is with 1000 rows, and there could be more, it takes a couple of seconds to allocate all the memory.
Is there any faster/better method to doing this?
EDIT:
Is there an advantage to using one of these methods over the other, besides the obvious simpler code?
char **FileTables;
int rows = 1000;
int i;
FileTables = malloc(rows * sizeof(char*));
FileTables[0] = malloc(rows * 256 * sizeof(char));
for (i = 0; i < rows; i++) {
FileTables[i] = FileTables[0] + i * 256;
}
And..
char (*FileTables)[256];
int rows = 1000;
FileTables = malloc(rows * sizeof(*FileTables));
(And yes, I fixed the unnecessary casting)
You could get away with just two allocations and some pointer arithmetic:
int rows = 1000;
int cols = 256;
char *data;
char **FileTables;
int i;
data = malloc(rows * cols);
FileTables = malloc(rows * sizeof(char*));
for (i = 0; i < rows; i++) {
FileTables[i] = data + i * cols;
}
Also note that I fixed a bug in malloc(rows * sizeof(char)) (the sizeof(char) should be sizeof(char*), since you're allocating an array of pointers to char).
As long as the number of columns is constant, or if you're using C99, you can get away with a single malloc without having to do ugly row/column addressing arithmetic yourself:
char (*FileTables)[256] = malloc(rows * sizeof *FileTables);
If the array is always of the size row × 256, then you might consider a one-dimensional array malloc(row * 256), and access it in strides:
char get(unsigned i, unsigned j, char * array) { return array[j + 256 * i]; }
void set(char value, unsigned i, unsigned j, char * array) { array[j + 256 * i] = value; }
This avoids multiple allocations and gives better memory locality. On top of that, you can pick row or column ordering to micro-optimize.
char **FileTables;
int rows = 1000;
int i;
FileTables = (char**)malloc(rows * sizeof(char *));
char *data = (char *)malloc(256 * 1000 * sizeof(char));
for (i = 0; i < rows; ++i) {
FileTables[i] = data;
data += 256 * sizeof(char);
}
Should be a better solution.
I don't believe you will get anywhere near seconds. Increasing the rows to 10 million is still under a second on my machine.
However if you want to minimise allocations, you only need one.
FileTables = (char**) malloc(rows * (sizeof(char *) + 256*sizeof(char)));
FileTables[0] = (char *) &FileTables[rows];
for (i = 1; i < rows; i++) {
FileTables[i] = FileTables[i-1] + 256 * sizeof (char);
}
free(FileTables);
A more efficient way to do this is to avoid the second level of indirection.
typedef char chars[256];
int main(int argc, char** argv) {
chars* FileTables;
int rows = 100000000;
int i;
FileTables = (chars*) malloc(rows * sizeof (chars));
free(FileTables);
return (EXIT_SUCCESS);
}
This avoid a pointer lookup as the C can calculate the rest.
First of all, are you sure it's the memory allocation that is the problem? allocating 1000 blocks of memory should generally not take a few seconds.
You could look into alternate malloc implementations if you have particular needs (e.g., google's tcmalloc if you are allocating memory in threads).
Otherwise, the real "slow" part of malloc is actually getting memory from the OS (with sbrk() or mmap()), and most malloc implementations will grab a big chunk at a time and give it back in smaller pieces, so there are not 1000 calls to allocate 1k each here, there are maybe 60 calls to allocate 16k. Running the program under strace or similar may give you an idea of how many slow system calls are really being made.. You could implement similar behavior yourself, by making a single call to allocate 256K and subdividing that up into smaller chunks. You could try allocating a big chunk of memory and then immediately free()-ing it and hope that the library malloc holds onto that memory and doesn't go back to the OS for more.
This really looks like premature optimization; because, you are asking for faster, but you haven't indicated how fast is fast enough. Still, if you really need to do it this way...
Tips to speed up allocation:
Do fewer allocations
Do smaller allocations
As you can see, if you need 10M allocated, these tips soon become conflicting. To determine the right balance between smaller and fewer allocations, on needs to do profiling.
Look to your memory block size and allocate whole pages of memory at once. It's an old hardware hack, but it does guarantee that you don't ask for multiple pages of continuous memory at once (which speeds up the selecting from the free page lists), and it also guarantees that you don't waste some cycles address space by asking for addresses already reserved by the block reservation subsystem of the memory manager.
If that doesn't get you the performance you need, then rewrite the code to not require allocation the way it's been presented.
Either way, it's not possible to guarantee optimum allocation speed without detailed knowledge of how the memory management subsystem on your computer is actually designed.

Dynamic allocation (malloc) of contiguous block of memory

For an assignment, I have to allocate a contiguous block of memory for a struct, but I'm first trying to do it with a 2D array of ints first and see if I understand it correctly. We had an example in the book that creates a block of memory for the pointer array (rows), and then initializes the cols and points the pointer to them. This example was:
int **CreateInt2D(size_t rows, size_t cols)
{
int **p, **p1, **end;
p = (int **)SafeMalloc(rows * sizeof(int *));
cols *= sizeof(int);
for (end = p + rows, p1 = p; p1 < end; ++p1)
*p1 = (int *)SafeMalloc(cols);
return(p);
}
void *SafeMalloc(size_t size)
{
void *vp;
if ((vp = malloc(size)) == NULL) {
fputs("Out of mem", stderr);
exit(EXIT_FAILURE);
}
return(vp);
}
I basically need to do what the above code does except make it one contiguous block of memory. The constraint is I'm only allowed to call malloc once, and then I have to use pointer math to know what to initialize the pointers to. So I thought I would initialize enough memory with something like:
int *createInt2D(size_t rows, size_t cols)
{
malloc(rows * sizeof(int *) + (row + cols) * sizeof(int));
}
But that doesn't seem quite right since I would think I would have to typecast the void * returned from malloc, but it's a combination of int and int*. So I'm not quite sure if I'm on the right track. Thoughts?
If you want a contiguous array, you should malloc(rows * cols * sizeof(int)).
Then you'd access arr[x, y] like:
arr[x * cols + y]
You are on the right track. The block returned by malloc is guaranteed to be aligned properly for either int * or int; you can use it for either. Typecasting isn't a one time operation.
If you are going to use array[row, col] addressing exclusively, you can get by without allocating extra space for the row pointers. If you would like to be able to use array[row] to get an int * column list, you'll have to include space for the column pointers in your allocation.
Hope that's enough to help with your exercise.
malloc((row * cols) * sizeof(int));
It's row*cols which is number of elements in the 2D array and not row+cols.
No need to multiply by the size of int *. That's only used to allocate the pointers for the rows. Same too with the sum of rows and cols. It's sufficient to allocate (rows * cols) * sizeof whatever structure is being allocated.

Optimal way to free() a malloc'ed 2D array in C

Supposing I have a 2 dimensional array which was created with something like this,
char **foo = (char **) malloc(height * sizeof(char *));
for(i = 0; i <= height; i++)
foo[i] = (char *) malloc (width * sizeof(char *));
First of all, Is this even the right way to create an array like this?. The catch here is, 'height' and 'width' is something that is set during runtime.
This seems to work, but which is the best strategy to free this 2d array.
free(funge) sounds wrong. Going by some other posts in here, I guess I will have free each row one by one?
I did try something like this,
for (height = 0; height < ip_ptr->funge_height; height++) {
free(funge[height]);
}
free(funge)
This, however gives me a double free pointer exception. Does this mean, I don't have to manage this piece of memory?. I was of the impression that, for every malloc'ed memory we should call free().
Since all the 'rows' are the same size, you can just allocate it in one swoop, with malloc(height * width * sizeof (char *)) (it's not entirely clear whether you're creating a 2d array of char or a 2d array of char *). You can use multiplication to calculate the appropriate index (i.e. foo[i][j] becomes foo + i * height + j),
free()ing it will similarly, take a single call.
In the for loop for allocation you are using i <= height; instead of i < height;. So you are writing to an invalid memory location and the behavior of your code becomes unpredictable.
The second allocation should be:
foo[i] = (char *) malloc (width * sizeof(char));
you're also looping height+1 times while allocating.
Besides that, those two snippets seem right to me, so the error should be elsewhere.
If the array was allocated as just one big chunk of memory, then you'd have to free it just once.
char **foo = (char **) malloc(height * sizeof(char *));
*foo = malloc(height * width * sizeof(char))
for (int i = 1; i < height; i++) {
foo[i] = *foo + i*width;
}
//and you just do 2 frees
free(*foo);
free(foo);
The mechanism to allocate is OK (though you should use sizeof(char) instead of sizeof(char *) in the allocate loop; you are overallocating the character strings) given that width and height are runtime values.
Your impression that you should call free() once for each malloc() is basically correct (things like calloc() and realloc() complicate the simple story).
The loop followed by free should be correct (or, at least, the general mechanism of 'free the sub-arrays first, then the array of pointers to sub-arrays) - so you need to review where the double free error is coming from. We can't see where the ip_ptr->funge_height was controlled; it is not immediately obvious that funge is described by ip_ptr->funge_height.
See the answer from 'unknown # google' - there's an array bounds problem.
When you allocate the memory, it should be i < height as the loop condition.
When you deallocate the memory, you should iterate up to the same index as you did when allocating. ip_ptr->funge_height should be the same as the original height, but it's not obviously so.
Other than that, it should work.
Here's another way, that involves fewer mallocs and frees.
To allocate:
char **foo = malloc (height * sizeof (char **));
foo[0] = malloc (height * width * sizeof (char *));
for (i = 1; i < height; ++i) {
foo[i] = foo[i-1] + width;
}
To deallocate:
free (foo[0]);
free (foo);
Allocation (assuming height > 0 and width > 0)
char **foo, *row;
assert(height > 0 && width > 0);
foo = malloc(height * sizeof *foo);
row = malloc(height * width * sizeof *row);
assert(foo != NULL && row != NULL);
for (i = 0; i < height; ++i, row += width)
foo[i] = row;
assert(row == *foo + height * width);
Deallocation
assert(foo != NULL);
free(*foo);
free(foo);
In such cases you can always use valgrind. Just compile your executable and run it:
valgrind --leak-check=full ./a.out
Valgrind will find all your memory validations and point to the code lines involved.
In your case it may have find the indexing problem (< vs. <=) easily.
If your compiler supports it, you could use a pointer to a variable-length array, ie
size_t width = 10, height = 5;
char *(*foo)[height][width] = malloc(sizeof *foo);
Keep in mind that you'll have to derefence the pointer before accessing the array elements, eg
(*foo)[1][2] = "foo";
This has the benefit that you'll only allocate a single, continuous block of memory which can be deallocated with a single call fo free().
This 100% works without exe crash.
char **map2d;
map2d=(char **)malloc(MAXY*sizeof(char *));
for(int a=0; a<MAXY; a++)
map2d[a]=(char *)malloc(MAXX*sizeof(char));
for(int a=0; a<MAXX; a++)
free(map2d[a]);
free(map2d);

Resources