Using memmove to move element in array - c

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.

Related

Dynamic array using malloc and realloc?

I'm trying to collect input integers one by one. My array starts with size 1 and I want to expand it by 1, with every input collected (is this a smart thing to do?)
Anyway, this is the code I managed to come up with, but it's not working as intended.
After this process, sizeof(array) always returns 8, which I assume means that the array is only being resized once. (sizeof(int) is 4 bits)
Trying to output the array results in multiple instances of the first input variable.
OUTPUT CODE
for(int s=0;s<sizeof(array)/sizeof(int);s++){
printf("%i\n",array[i]);
}
ORIGINAL CODE:
int i;
int size = 1;
int *array = malloc(size * sizeof(int));
int position = 0;
do{
i = getchar() - 48;
f (i != -16 && i != -38 && i != 0) {
array[position] = i;
position++;
size++;
*array = realloc(array, size * sizeof(int));
}
} while (i != 0);
UPDATED STILL NOT WORKING CODE
int i;
int size = 1;
int *array = malloc(size * sizeof(int));
int position = 0;
do{
i = getchar() - 48;
f (i != -16 && i != -38 && i != 0) {
array[position] = i;
position++;
size++;
array = realloc(array, size * sizeof(int));
}
} while (i != 0);
array = realloc(...)
not *array. Per the realloc docs, realloc returns the pointer, which you can store directly in your array pointer.
Edit One thing that will make your life easier: use char constants instead of raw numbers. E.g.,
i = getchar();
if(i != ' ' && i != '\n' && i != '0') {
/* 48-16 48-38 48-0 right? */
array[position] = i - '0'; /* '0' = 48 */
One thing that jumps out at me: inside your loop, this line:
*array = realloc(array, size * sizeof(int));
should instead be:
array = realloc(array, size * sizeof(int));
In the original version, you were sticking the result of realloc in the first element of the array by dereferencing the pointer first. Without the asterisk, you're reassigning the array itself.
(With some copy-paste from my comment:) sizeof(array) returns 8 because it equals sizeof(int*) (array is type int*) which is 8 (you're probably compiling as 64-bit). sizeof doesn't work how you think for pointers to arrays.
Similarly, your output code is wrong, for the same reason. You only print the first two elements because sizeof(array)/sizeof(int) will always be 8/4=2. It should be
for(int s=0;s<size;s++){
printf("%i\n",array[s]);
}
(note also changed index variable i to s)
where size is the variable from your other code chunk(s). You cannot find the length of the array from sizeof if it's dynamically allocated with pointers; that's impossible. Your code must "remember" the size of your array.

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);

copying multidimensional array (pointers)

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;

Resources