copying multidimensional array (pointers) - c

I have two structs pointers to pointers
typedef struct Square {
...
...
}Square;
Square **s1; //Representing 2D array of say, 100*100
Square **s2; //Representing 2D array of say, 200*200
Both are allocated on the heap using malloc().
I have s1 initialized with certain values and s2 initialized completely with the default values.
Basically I need to resize s1 to the size of s2 while maintaining its (s1) values, and the 'added' values would be just as they were in s2 - the default value.
I wrote this question memcpy() from smaller array to larger one but apparently I'm confusing between arrays and pointers/
My question is, how to implement this resizing of s1 to the size of s2. I don't have to keep the original pointer. I can copy s1 to s2 and return s2 if that's a better way
I hope I explained what I'm after properly.
Thanks!

Two dimensional arrays are laid out in memory sequentially: row1 row2 row3 etc.
memcpy does a linear copy from one memory location to another.
So to achieve what you need:
a) Create a new array
Square **s3 = malloc(sizeof(s2));
b) Copy s2 into it
c) Copy stuff from s1, row by row into new
for(r = 0; r < NROWS_S1; r++)
memcpy(s3[r], s1[r], sizeof(Square) * NCOLS_S1);
http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html

You can try something like this:
typedef struct {
//
} Square;
Square** s1; // 100x100, needs to resize and be like s2.
Square** s2; // 200x200
void resize_s1()
{
// resize the outer array
s1 = realloc(s1, sizeof(Square*)*200);
memset(s1 + 100, 0, 100*sizeof(Square*)); // we initialize the newly allocated pointers to NULL
for(int i = 0; i < 200; ++i)
{
// resize the inner array. Since we initialized the last
// 100 pointers to null, realloc will just behave like
// malloc for them.
s1[i] = realloc(s1[i], 200*sizeof(Square));
// ... and copy the new values in! You can omit this step,
// but anything outside of the original bounds of s1 will
// be uninitialized. All your pointers will be valid though.
if(i >= 100)
memcpy(s1[i] + 100, s2[i] + 100, 100*sizeof(Square));
}
}
As a word of warning - I'm playing very fast and loose with realloc here. Read its man page for more details, but if you ever hit low memory conditions, bad things can happen.

You've allocated your 2-D matrix on the heap, and you're using a Square** to access it. This means that you've: (1) allocated the space for each element in one or more calls to malloc, and (2) allocated the space for all of the row pointers in a call to malloc. How to proceed depends quite a lot of how you've allocated the array.
Below, I use assert to stress that each malloc/realloc can return NULL (indicating that it could not complete the request). You'll probably want to handle these cases properly.
Option 1: You allocated each row separately
You allocated the s1 matrix like this:
Square** s1 = malloc(M1*sizeof(s1[0]));
for (size_t i=0; i < M1; i++)
s1[i] = malloc(N1*sizeof(s1[i][0]));
In this case, you have to handle each row separately:
/* M1 and N1 set to size of s1 (M1 x N1) */
/* M2 and N2 set to size of s2 (M2 x N2) */
/* First, reallocate the pointers to each row */
Square** tmpRows = realloc(s1, M2*sizeof(*tmpRows));
assert( (tmpRows != NULL) && "Out of memory reallocating rows" );
s1 = tmpRows;
/* Now, reallocate each row */
for (size_t i=0; i < M1; i++) {
Square* tmpVals = realloc(s1[i], N2*sizeof(tmpVals[0]));
assert( (tmpVals != NULL) && "Out of memory reallocating row" );
/* copy elements of s2 into new column */
memcpy(tmpVals+N1, s2[i]+N1, (N2-N1)*sizeof(s1[i][0]));
s1[i] = tmpVals;
}
/* Now, allocate each new row of s1 and copy the additional rows of s2 into s1 */
for (size_t i=M1; i < M2; i++) {
s1[i] = malloc( N2 * sizeof(s1[i][0]) );
assert( (s1[i] != NULL) && "Out of memory allocating new row" );
memcpy(s1[i], s2[i], N2*sizeof(s1[i][0]));
}
Option 2: You allocated each all of the rows at once
In this case, you allocated all of the rows in one big chunk, and then assigned pointers to the beginning of each row. Like this:
Square** s1 = malloc(M1*sizeof(s1[0]));
s1[0] = malloc( M1*N1*sizeof(s1[0][0]) );
for(size_t i=1; i < M1; i++)
s1[i] = s1[i-1] + N1;
To resize the array (and initialize its new elements with those of s2), you should do the following:
/* M1 and N1 set to size of s1 (M1 x N1) */
/* M2 and N2 set to size of s2 (M2 x N2) */
/* Make a new copy of the elements of s1. Linear layout of a 200x200
* matrix will be different than the linear layout of a 100x100 matrix.
* Making a new copy makes it easier to initialize its values.
*/
Square* new_mat = malloc( M2*N2*sizeof(new_mat[0]) );
assert( (new_mat != NULL) && "Out of memory allocating new matrix" );
/* Initialize with values of s2. Assumption: s2 is also allocated
* as a contiguous array...
*/
memcpy(new_mat, s2[0], M2*N2*sizeof(s2[0][0]));
/* Now, reallocate the rows */
Square** tmpRows = realloc(s1, M2*sizeof(s1[0]));
assert( (tmpRows != NULL) && "Out of memory reallocating rows" );
s1 = tmpRows;
/* Copy data from old rows into new rows... */
for (size_t i=0; i < M1; i++) {
/* rows of s1 still point to old_mat data, copy it into new_mat.
* Each row in new_mat starts at (new_mat + N2*i)
*/
memcpy( new_mat + N2*i, s1[i], N1*sizeof(s1[i][0]) );
}
/* Free old memory and assign new row pointers... */
free(s1[0]);
s1[0] = new_mat;
for (size_t i=1; i < M2; i++)
s1[i] = s1[i-1] + N2;

Related

Using memmove to move element in array

I allocated a multi-dimensional array using malloc. After I process an element I have to delete it from the array and reallocate the correct amount of memory. So I used memmove to overwrite the array moving the elements that are in the next position with respect to the one I processed in its position.
float **dataset = (float**)malloc(CHUNK * sizeof(float *));
for (int i = 0; i < CHUNK; i++) {
dataset[i] = (float *) malloc((d + 1) * sizeof(float));
if(dataset[i] == NULL){
printf("Something went wrong in load_dataset(), memory allocation failed!");
exit(1);
}
}
[... filling the dataset and other stuff...]
/* now I want to move all the elements from the second one,
back of 1 position and then reallocate dataset
to have one less dimensoin*/
memmove(dataset[0], dataset[1], 20 * sizeof(float*));
But it only moves the first 4 elements.

Import a matrix of any size in C [duplicate]

How am I supposed to use dynamic memory allocations for arrays?
For example here is the following array in which i read individual words from a .txt file and save them word by word in the array:
Code:
char words[1000][15];
Here 1000 defines the number of words the array can save and each word may comprise of not more than 15 characters.
Now I want that that program should dynamically allocate the memory for the number of words it counts. For example, a .txt file may contain words greater that 1000. Now I want that the program should count the number of words and allocate the memory accordingly.
Since we cannot use a variable in place of [1000], I am completely blank at how to implement my logic. Please help me in this regard.
You use pointers.
Specifically, you use a pointer to an address, and using a standard c library function calls, you ask the operating system to expand the heap to allow you to store what you need to.
Now, it might refuse, which you will need to handle.
The next question becomes - how do you ask for a 2D array? Well, you ask for an array of pointers, and then expand each pointer.
As an example, consider this:
int i = 0;
char** words;
words = malloc((num_words)*sizeof(char*));
if ( words == NULL )
{
/* we have a problem */
printf("Error: out of memory.\n");
return;
}
for ( i=0; i<num_words; i++ )
{
words[i] = malloc((word_size+1)*sizeof(char));
if ( words[i] == NULL )
{
/* problem */
break;
}
}
if ( i != num_words )
{
/* it didn't allocate */
}
This gets you a two-dimensional array, where each element words[i] can have a different size, determinable at run time, just as the number of words is.
You will need to free() all of the resultant memory by looping over the array when you're done with it:
for ( i = 0; i < num_words; i++ )
{
free(words[i]);
}
free(words);
If you don't, you'll create a memory leak.
You could also use calloc. The difference is in calling convention and effect - calloc initialises all the memory to 0 whereas malloc does not.
If you need to resize at runtime, use realloc.
Malloc
Calloc
Realloc
Free
Also, important, watch out for the word_size+1 that I have used. Strings in C are zero-terminated and this takes an extra character which you need to account for. To ensure I remember this, I usually set the size of the variable word_size to whatever the size of the word should be (the length of the string as I expect) and explicitly leave the +1 in the malloc for the zero. Then I know that the allocated buffer can take a string of word_size characters. Not doing this is also fine - I just do it because I like to explicitly account for the zero in an obvious way.
There is also a downside to this approach - I've explicitly seen this as a shipped bug recently. Notice I wrote (word_size+1)*sizeof(type) - imagine however that I had written word_size*sizeof(type)+1. For sizeof(type)=1 these are the same thing but Windows uses wchar_t very frequently - and in this case you'll reserve one byte for your last zero rather than two - and they are zero-terminated elements of type type, not single zero bytes. This means you'll overrun on read and write.
Addendum: do it whichever way you like, just watch out for those zero terminators if you're going to pass the buffer to something that relies on them.
While Ninefingers provided an answer using an array of pointers , you can also use an array of arrays as long as the inner array's size is a constant expression. The code for this is simpler.
char (*words)[15]; // 'words' is pointer to char[15]
words = malloc (num_words * sizeof(char[15]);
// to access character i of word w
words[w][i];
free(words);
If you're working in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_LEN 15
int resizeArray(char (**wordList)[WORD_LEN], size_t *currentSize, size_t extent)
{
int result = 1;
char (*tmp)[WORD_LEN] = realloc(*wordList,
(*currentSize + extent) * sizeof **wordList);
if (tmp)
{
*currentSize += extent;
*wordList = tmp;
}
else
result = 0;
return result;
}
int main(void)
{
char *data[] = {"This", "is", "a", "test",
"of", "the", "Emergency",
"Broadcast", "System", NULL};
size_t i = 0, j;
char (*words)[WORD_LEN] = NULL;
size_t currentSize = 0;
for (i = 0; data[i] != NULL; i++)
{
if (currentSize <= i)
{
if (!resizeArray(&words, &currentSize, 5))
{
fprintf(stderr, "Could not resize words\n");
break;
}
}
strcpy(words[i], data[i]);
}
printf("current array size: %lu\n", (unsigned long) currentSize);
printf("copied %lu words\n", (unsigned long) i);
for (j = 0; j < i; j++)
{
printf("wordlist[%lu] = \"%s\"\n", (unsigned long) j, words[j]);
}
free(words);
return 0;
}
If you intend to go for C++, STL is very useful for something dynamic allocation and is very easy. You can use std::vector ..
In modern C (C99) you have an additional choice, variable length arrays, VLA, such as that:
char myWord[N];
In principle you could also do such a thing in two dimensions, but if your sizes get too big, you may risk a stack overflow. In your case the easiest thing would be to use a pointer to such an array and to use malloc / realloc to resize them:
typedef char Word[wordlen];
size_t m = 100000;
Word* words = malloc(m * sizeof(Word));
/* initialize words[0]... words[m-1] here */
for (size_t i = 0; i < m; ++i) words[i][0] = '\0';
/* array is too small? */
m *= 2;
void *p = realloc(words, m*sizeof(Word));
if (p) words = p;
else {
/* error handling */
}
.
free(words);
This code should work (modulo typos) if wordlen is a constant or a variable, as long as you keep everything inside one function. If you want to place it in a function you should declare your function something like
void myWordFunc(size_t wordlen, size_t m, char words[m][wordlen]);
that is the length parameters must come first to be known for the declaration of words.
If the 15 in your example is variable, use one of the available answers (from Ninefingers or John Boker or Muggen).
If the 1000 is variable, use realloc:
words = malloc(1000 * sizeof(char*));
// ... read 1000 words
if (++num_words > 1000)
{
char** more_words = realloc(words, 2000 * sizeof(char*));
if (more_words) {printf("Too bad");}
else {words = more_words;}
}
In my code above, the constant 2000 is a simplification; you should add another variable capacity to support more than 2000 words:
if (++num_words > capacity)
{
// ... realloc
++capacity; // will reallocate 1000+ words each time; will be very slow
// capacity += 1000; // less reallocations, some memory wasted
// capacity *= 2; // less reallocations but more memory wasted
}
Here is a little information on dynamically allocating 2d arrays:
http://www.eskimo.com/~scs/cclass/int/sx9b.html
char ** words = malloc( 1000 * sizeof(char *));
int i;
for( i = 0 ; i < 1000 ; i++)
*(words+i) = malloc(sizeof(char) * 15);
//....
for( i = 0 ; i < 1000 ; i++)
free(*(words+i));
free(words);

Create vector char array of strings

I am trying to create an array of c string in C, which simulates a behavior similar to that of vector array in c++. The array doubles its capacity whenever the (currentSize + 1) is equal to (MAX_SIZE). This is how I am doing it:
void addLog(char ** dynamicArray, int* size, int *maxSize, int command){
if (*size < *maxSize){
dynamicArray[*size] = "User selects option 1 from main menu.";
(*size)++;
}
else{
//resizing the array here
int originalSize = *maxSize;
*maxSize = *maxSize * 2;
//copy elements of dynamic array in temporary array
char **tempArray = (char**)malloc(originalSize * sizeof(char*));
for (int i = 0; i < originalSize; ++i){
memcpy(&tempArray[i], &dynamicArray[i], sizeof(dynamicArray[i]));
}
//create new array of max * 2 size
dynamicArray = (char**)malloc(*maxSize * sizeof(char*));
//copy temp to dynamic
for (int i = 0; i < originalSize; ++i){
memcpy(&dynamicArray[i], &tempArray[i], strlen(tempArray[i]));
}
for (int i = 0; i < originalSize; i++) {
free(tempArray[i]); <---- this throws an exception on heap
}
free(tempArray);
//insert new element now
dynamicArray[*size] = "User selects option 1 from main menu.";
(*size)++;
}
}
I believe this is a trivial problem for a deep copy scenario. How to resize dynamic array to 2 * capacity and then free the temporary existing elements?
You could create a reusable implementation yourself by extending a struct.
This is a bit long, but it walks you through the entire process and should have everything you need to know:
http://eddmann.com/posts/implementing-a-dynamic-vector-array-in-c/
The structure will take advantage of a fixed-size array, with a counter invariant that keeps track of how many elements are currently present. If the underlying array becomes exhausted, the addition operation will re-allocate the contents to a larger size, by way of a copy."

error realloc 2D array

I would like to realloc a 2D array. I have a counter, itime it increases each step. Each step, I would like to reallocate my array, keeping the old values, and add new values to the array. When itime=1, I use only malloc, because it is allocated for the first time. When itime increases (e.q. itime=2), realloc is used. In the realloc process my GUI crashes.
Can somebody tell me the reason of the crash, Have I reallocated correctly?
int itime;
char ** solpointer;
for( itime = 1 ; itime <= 4 ; itime++ ) {
if( itime == 1 ) {
solpointer = (char**)malloc(sizeof(char*) * itime);
solpointer[itime-1] = (char*)malloc(sizeof(char) * 32);
}
else {
solpointer = (char**)realloc(solpointer, sizeof(char*) * itime);
solpointer[itime-1] = (char*)malloc(sizeof(char) * 32 );
}
}

C malloc error freeing struct

I've just re-start learning C, but i'm really confused with some memory management details.
I'm getting
pointer being freed was not allocated ... Abort trap
for the code below. Do i really need 1 free per malloc? Why my code is wrong?
Thanks!
#define N 9
typedef struct
{
int MAX_LIST_SIZE;
int length;
int *ini;
}List;
/* allocates new List and its data */
List *newList(int size)
{
List *list = malloc(sizeof(List));
list->MAX_LIST_SIZE = size;
list->length = 0;
list->ini = malloc(sizeof(int) * size);
return list;
}
/* add some value to the list */
void addList(List *list, int val)
{
if (list->length < list->MAX_LIST_SIZE)
list->ini[list->length++] = val;
else
fprintf(stderr, "Error: add(): List is full.\n");
}
/* get an array of N*N lists malloc-ed Lists */
List *gridList()
{
int i, j;
List *cells = malloc(sizeof(List) * N * N);
for (i = 0; i < N * N; i++)
{
/* malloc is called inside NewList()*/
cells[i] = *newList(N);
for (j = 0; j < N; j++)
addList(&cells[i], j + 1);
}
return cells;
}
/* inside main */
List *cells = gridList();
/* use cells ... */
/* free */
for (i = 0; i < N * N; i++)
{
free(cells[i].ini);
/* line below causes CRASH */
free(&cells[i]);
}
You do :
cells[i] = *newList(N);
which sets each element in cells to a copy of the list dynamically allocated by newList. So newList dynamically allocates a list, then you take the pointer to that dynamically allocated List, dereference it, and copy it into cells[i]. So then later on when you go to free() each element:
free(&cells[i]);
It doesn't work because each element in cells[i] is a List, not a List * (list pointer) allocated by malloc().
So you have two options. One (bad one) is to just remove that last free() line since there's nothing to free. However, this just covers up a larger problem which is that you now have memory leaks because you can't go back and free the dynamically allocated Lists created with newList().
Instead it's likely you want to have an array of pointers to the lists, which you can do by changing it to:
List **cells = malloc(sizeof(List*) * N * N);
so that cells[i] refers to a List *. newList() returns such a pointer, so you would change that line to:
cells[i] = newList(N);
similarly, addList() takes such a pointer, so you'd simply change that line to:
addList(cells[i], j + 1);
since &cells[i] would pass it the address of the pointer, which is not what you want.
Finally, change the free statements to:
free(cells[i]->ini); // ->init because cells[i] is now a pointer to a List, List *
free(cells[i]);
The problem is you are allocating an array of lists, copying the full contents of your lists into the array elements, and then trying to free them. The original allocated List records are a memory leak, and the free calls are indeed trying to free memory that was not malloc'ed (or more exactly were malloc'ed in a single big block).
You want an array of pointers to pointers to hold your lists:
/* get an array of N*N lists malloc-ed Lists */
List **gridList()
{
int i, j;
// VV note change here
List **cells = malloc(sizeof(List*) * N * N);
for (i = 0; i < N * N; i++)
{
/* malloc is called inside NewList()*/
cells[i] = newList(N); // << Note change here.
for (j = 0; j < N; j++)
addList(cells[i], j + 1);
}
return cells;
}
/* free */
for (i = 0; i < N * N; i++)
{
free(cells[i]->ini); // << and here
/* line below causes CRASH */
free(cells[i]); // << and here
}
free(cells);

Resources