i'm getting unexpected behavior using realloc - c

for some reason, every 2-3 times that i run the program i get unexpected values, such as -842150451 -842150451, and every other time i get the correct result: 7 9.
i'm a student, so sorry if the code is a little academic.
please see code:
int mat[ROW][COL] = {
{2,-3,5,1,2},
{2,4,7,7,1},
{1,9,7,3,0}
};
int row, col, tempRow = 0, tempCol = 0, indexCol, indexRow = 0, loopTempRow, flag = 0, cnt = 1, loopTempCol = 0;
int* arr;
int* ptrArr;
arr = (int*)malloc(cnt * sizeof(int)); // mallocating an array with size 1 * int
ptrArr = arr;
if (arr == NULL) // checking allocation done succefully
{
printf("Error Allocating Memory\n");
exit(1);
}
for (row = 0; row < ROW; row++) // starting from row 0 we will wheck col 0,1,2,3,4 for the highest val.
{
flag = 1;
tempCol = 0;
for (col = 0; col < COL; col++)
{
if (mat[row][col] > tempCol)
{
tempCol = mat[row][col];
indexCol = col;
}
}
for (loopTempRow = 0; loopTempRow < ROW; loopTempRow++) // then we will check the row of the col index
{
if (mat[loopTempRow][indexCol] > tempCol)
{
flag = 0;
break;
}
}
if (flag == 1)
{
cnt++; // this is a counter for realloctaing.
arr = realloc(arr, (cnt - 1) * sizeof(int)); // every iteration the arr is increasing by 1
printf("mat[%d][%d] = %d\n", row, indexCol, mat[row][indexCol]);
*ptrArr = mat[row][indexCol]; // inserting the element into the arr
ptrArr++;
}
}
if (cnt == 1) // if the cnt = 1, it means that flag didn't became 1. which meant no value inserted to the arr
arr = NULL;
for (ptrArr = arr; ptrArr - arr < cnt - 1; ptrArr++) // print arr
printf("%d\t", *ptrArr);
free(arr);
}
i suspect that the problem is with the realloc block:
if (flag == 1)
{
cnt++; // this is a counter for realloctaing.
arr = realloc(arr, (cnt - 1) * sizeof(int)); // every iteration the arr is increasing by 1
printf("mat[%d][%d] = %d\n", row, indexCol, mat[row][indexCol]);
*ptrArr = mat[row][indexCol]; // inserting the element into the arr
ptrArr++;
}
}

You initially allocate an array with room for one integer, but you never set that integer value. I guess it is because allocating a block of 0 bytes returned NULL which you assume is an error.
Another confusing code fragment is
cnt++; // this is a counter for realloctaing.
arr = realloc(arr, (cnt - 1) * sizeof(int)); // every iteration the arr is increasing by 1
Why initializing cnt to 1 if you want that the size of the allocated array is the number of times we had flag == 1 ?
Beside, you never write any value in this array. Assigning a value to *ptrArr would at best overwrite the first value of the array.
Another problem it that you initially copy arr to ptrArr. Later, if flag == 1 you reallocate arr. A reallocation implies that the input array may be deallocated (free) and a new bigger block is allocated. In this case, when you later assign a value to *ptrArr you won’t write in arr. You will write in deallocated space where you should not write. Worse, if that space is reallocated in the mean time, you may override valid data by mistake, which is a very nasty problem to debug.
I have the impression that you assume that reallocation creates space in front of the block. That is not correct. ralloc, extends the block. So room is added at the end of the block when its size grows.
This implies that you have to append mat[row][indexCol] to the array arr when flag == 1.
Here is how you should handle your array.
// initialize the array as empty
int cnt = 0;
int *arr = NULL;
Note that allocating a block of 0 bytes is implementation dependent. It may or may not return NULL. Here we decide that an empty array is NULL and has cnt == 0.
The following code appends the value mat[row][indexCol] to the array:
// append mat[row][indexCol] to the array arr
arr = realloc(arr, (cnt+1)*sizeof(int));
arr[cnt++] = mat[row][indexCol];
This works when arr is NULL because realloc will allocate a new block.
To print all values in the array:
for(int i = 0; i < cnt; i++)
printf("%d\t", arr[i]);
It doesn’t matter if arr == NULL when cnt == 0 because arr is never accessed when cnt == 0.
There is also a mistake in the code that locates the biggest value in a row.
You initialize tempCol with 0, and compare values with it. If the row contains only negative values that are all smaller than 0, your algorithm will fail to find the biggest value in the row.
In order to find the biggest value in a row, you have two options.
Initialize tempCol with the smallest possible value : INT_MIN (#include <limits.h>).
Use the following code that removes the need of tempCol.
indexCol = 0;
for (col = 1; col < COL; col++)
if (mat[row][col] > mat[row][indexCol])
indexCol = col;
// here, indexCol is the index of biggest value in the row

Your problem is mostly likely due to using ptrAtr. You initialise it to the start of arr, but later on you realloc arr and there is no guarantee that arr will remain at the same memory location which means that ptrArr will no longer point into it.
You'd be better off with using an index into arr like this..
int cnt = 0;
arr = (int*)malloc(cnt * sizeof(int));
// stuff happens
if (flag == 1)
{
arr = realloc(arr, (cnt + 1) * sizeof(int));
printf("mat[%d][%d] = %d\n", row, indexCol, mat[row][indexCol]);
arr[cnt++] = mat[row][indexCol];
}
}

Related

Recursive realloc() throw "invalid next size" after the 7th cicle

So, I have a pointer which need to increase it's "length" until the user insert a negative number or "e". It starts with the length of "1", via a malloc() then I use into a do{...} while(...) loop the realloc() function to increase its lenght. Here's the code:
int *array = malloc (sizeof(int) * 1);
bool exit = false;
int lastIndex = 0, value;
do {
printf ("Insert a positive number. Insert a negative number or \"e\" to exit: ");
int scanf_result = scanf("%i", &value);
if (scanf_result) {
if (value >= 0) {
array[lastIndex] = value;
lastIndex++;
array = (int*) realloc (array, lastIndex * sizeof(int));
} else {
exit = true;
}
} else {
exit = true;
}
} while (!exit);
I can't figure out why after the 7th cicle it exit with the error realloc(): invalid next size.
Any idea? Thanks in advice for help.
You're not reallocating enough memory:
array = (int*) realloc (array, lastIndex * sizeof(int));
On the first iteration of the loop, lastIndex is incremented from 0 to 1, then you run the above realloc call. Since lastIndex is 1, you still only have enough space for 1 element. As a result, you write past the end of allocated memory on the next iteration.
This invokes undefined behavior, which in your case manifests as appearing to work properly for the first 6 iterations and failing on the 7th. It could have just as easily crashed on the first or second iteration.
Add one to the size you're allocating:
array = realloc(array, (lastIndex + 1) * sizeof(int));
Also, don't cast the return value of malloc/realloc.
Fix your realloc:
array = (int*) realloc (array, (lastIndex + 1) * sizeof(int))
You are allocating one item less than you need to.

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.

C - creating a struct with input-dependent number of arrays

I’m wondering if anyone could provide any advice on storing “class slices” of values? I.e., for a table of values (see below for example), I want to be able to store, for each row, an array of the values that corresponds to each class. I have already sorted the table by class and determined the number of classes and the number of elements in each class. I’ve written out the basic conditions that I think will let me iterate over each row, over each class with the goal of copying the values from one struct into the new “class slice arrays”:
int x = 0;
for(int i = 0; i < total_rows - 1; i++)
{
for (int j = 0; j < n_classes; j++)
{
for (int k = 0; k < class_size[j]; k++)
{
data[x].value[i] = // value at the xth position of the “class slice” array for the jth class of values in the ith row //
x++;
}
}
}
where data[x].value[0] is the value I have stored for the xth sample in row i.
I guess my question is - how would you start mallocing space for arrays to store these class slices if you don’t know how many you’re even going to need (since that’s dependent on the number of rows and the number of classes)?
Example input, if this helps to make it clearer:
Class Case Case Case Case Case Case Case Case Case Case Case Case Case Case Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control
Obs1 0.000741628 0.00308607 0.000267431 0.001418697 0.001237904 0.000761145 0.0008281 0.002426075 0.000236698 0.004924871 0.000722752 0.003758006 0.000104813 0.000986619 0.000121803 0.000666854 0 0.000171394 0.000877993 0.002717391 0.001336501 0.000812089 0.001448743 5.28E-05 0.001944298 0.000292529 0.000469631 0.001674047 0.000651526 0.000336615
Obs2 0.102002396 0.108035127 0.015052531 0.079923731 0.020643362 0.086480609 0.017907667 0.016279315 0.076263965 0.034876124 0.187481931 0.090615572 0.037460171 0.143326961 0.029628502 0.049487575 0.020175439 0.122975405 0.019754837 0.006702899 0.014033264 0.040024363 0.076610375 0.069287599 0.098896479 0.011813681 0.293331246 0.037558052 0.303052867 0.137591517
Obs3 0.218495065 0.242891829 0.23747851 0.101306336 0.309040188 0.237477347 0.293837554 0.34351816 0.217572429 0.168651691 0.179387106 0.166516699 0.099970652 0.181003474 0.076126675 0.10244981 0.449561404 0.139257863 0.127579104 0.355797101 0.354544105 0.262855651 0.10167146 0.186068602 0.316763006 0.187466247 0.05701315 0.123825467 0.064780343 0.069847682
Obs4 0.141137543 0.090948286 0.102502388 0.013063365 0.162060849 0.166292135 0.070215996 0.063535037 0.333743609 0.131011609 0.140936687 0.150108506 0.07812762 0.230704405 0.069792935 0.120770743 0.164473684 0.448110378 0.42599534 0.074094203 0.096525097 0.157661185 0.036737518 0.213931398 0.091119285 0.438073807 0.224921728 0.187034237 0.06611442 0.086005218
Obs5 0.003594044 0.003948354 0.008137536 0.001327901 0.002161974 0.003552012 0.002760334 0.001898667 0.001420186 0.003165988 0.001011853 0.001217382 0.000314439 0.004254794 0.000213155 0.003650147 0 0.002742309 0.002633978 0 0.002524503 0.002146234 0.001751465 0.006543536 0.003941146 0.00049505 0.00435191 0.001944054 0.001303053 0.004207692
Obs6 0.000285242 2.27E-05 0 1.13E-05 0.0002964 3.62E-05 0.000138017 0.000210963 0.000662753 0 0 0 0 4.11E-05 0 0 0 0 0.000101307 0 0 0 0 5.28E-05 0.00152391 0 0 0 0 0
Obs7 0.002624223 0.001134584 0.00095511 0.000419934 0.000401011 0.001739761 0.00272583 0.002566717 0.000520735 0.002311674 0.006287944 0 6.29E-05 0.000143882 3.05E-05 0.000491366 0 0 3.38E-05 0 0.001782002 0.000957104 0.002594763 0.000527704 0.000105097 0.001192619 3.13E-05 0 0.000744602 0.000252461
Obs8 0.392777683 0.383875286 0.451499522 0.684663315 0.387394299 0.357992026 0.488406597 0.423473155 0.27267563 0.47454646 0.331020526 0.484041709 0.735955056 0.338841956 0.781699147 0.625403622 0.313596491 0.270545891 0.379259109 0.498913043 0.372438372 0.446271644 0.606698813 0.305593668 0.360535996 0.29889739 0.328710081 0.521222594 0.419924299 0.584111756
I think what you are looking for is a struct containing a pointer to double and an int that keeps track of the number of values being stored:
struct data {
int numValues;
double *value;
};
If you don't know how many data structs you need, you declare a pointer to one, and allocate them as needed. Whenever you allocate a new data struct, you set the value to point to NULL. As you add values, you reallocate storage, reset the value pointer, and update the counter for that struct. Here is a little toy example to illustrate how it works:
#include <stdio.h>
#include <stdlib.h>
struct data {
int numValues;
double *value;
};
int main(void)
{
struct data *myData;
int numData = 0;
int i, last;
myData = NULL;
++numData;
i = numData - 1;
myData = realloc(myData, sizeof(*myData) * numData);
myData[i].numValues = 0;
myData[i].value = NULL;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 3.1415926536;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 2.7182818285;
printf("Value [0][0]: %lf\n", myData[i].value[0]);
printf("Value [0][1]: %lf\n", myData[i].value[1]);
++numData;
i = numData - 1;
myData = realloc(myData, sizeof(*myData) * numData);
myData[i].numValues = 0;
myData[i].value = NULL;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 1.6180340;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 2.99792458;
printf("Value [1][0]: %lf\n", myData[i].value[0]);
printf("Value [1][1]: %lf\n", myData[i].value[1]);
/* Let's free all of the memory we allocated! */
// first, free space allocated for values
for (int j = 0; j <= i; j++)
free(myData[j].value);
// next, free space allocated for structs
free(myData);
return 0;
}
Edit
I cleaned up the code a bit and stored a couple of numbers in a second struct in an attempt to make the example a little more illustrative. I also added a few lines to free the allocated memory.
I am not exactly sure what your data is representing, but it might be useful to add a second dynamic array to the struct:
struct data {
int numCase;
int numControl;
double *caseValue;
double *controlValue;
};
Some variation on this idea would allow you to keep your "case" and "control" values separate, and you could manage the addition of new values as before.

Connect-N Board Game, crashing when Width is >> Height

I'm in the process of coding a Connect-N board game, and I'm almost finished and have gone through troubleshooting. My problem is now after changing some stuff my game crashes when the computer plays its move if the Width is too much greater than the height. There are two functions involved here, so I will paste them both.
Board
*AllocateBoard(int columns, int rows)
{
int **array= malloc(sizeof(int *) *columns);
int r = 0;
for ( r = 0; r < columns; ++r)
{
array[r] = malloc(sizeof(int) * rows);
}
int j = columns - 1;
int k = rows - 1;
int m = 0;
int n = 0;
for ( m = 0; m < j; ++m)
{
for ( n = 0; n < k; ++n)
{
array[m][n] = 0;
}
}
Board *board = malloc(sizeof(Board));
board->columns = columns;
board->rows = rows;
board->spaces = array;
return board;
}
This first function allocates the board to be a matrix Width * Height that the user passes in via the command line. It then initializes every space on the board to be zero, and then stores the columns, rows, and spaces into a Board structure that I've created. It then returns the board.
int
computerMakeMove(Board *board)
{ int RandIndex = 0;
int **spaces = board->spaces;
int columns = board->columns;
int *arrayoflegalmoves = malloc(sizeof(int) * (columns));
int columncheck = 0;
int legalmoveindex = 0;
while (columncheck <= columns - 1)
{
if (spaces[columncheck][0] == 0)
{
arrayoflegalmoves[legalmoveindex] = columncheck;
++legalmoveindex;
++columncheck;
}
else
{
++columncheck;
}
arrayoflegalmoves = realloc(arrayoflegalmoves, (legalmoveindex) * sizeof(int));
}
if (legalmoveindex == 1)
{
return arrayoflegalmoves[0];
}
else
{
RandIndex = rand() % (legalmoveindex);
return arrayoflegalmoves[RandIndex];
}
}
This second function is designed to make the computer randomly pick a column on the board. It does this by checking the value of the top row in each column. If there is a zero there, it will store this value in an array of legal moves, and then it increments the legalmoveindex. If there isn't, it skips the column and checks the next. It ends when it gets finished checking the final column. If there is only one legal move, it will play it. If there are more, it will select a random index from the array of legal moves (I run srand in the main) and then return that value. It will only ever attempt to play on a legal board, so that's not the problem. I am pretty confident the problem occurs in this function, however, as I call the functions as follows
printf("Taking the computers move.\n");
{printf("Taking computer's move.");
computermove = computerMakeMove(playerboard);
printf("Computer's move successfully taken.\n");
playerboard = MakeMove(playerboard, computermove, player);
printf("Computer's board piece successfully played.\n");
system("clear");
displayBoard(playerboard);
...;
}
and it prints
Aborted (core dumped)
immediately after it prints
"Taking computer's move."
Once again, my question is: why is my program crashing if the width is larger than the height when the computer plays?
Thanks.
Edit: I found the solution and I am stupid.
I realloc'd during the while loop.
The realloc should be the first thing outside of the while loop.
The answer for any future programmers who may have this problem:
Notice the
while (columncheck <= columns - 1)
{
if (spaces[columncheck][0] == 0)
{
arrayoflegalmoves[legalmoveindex] = columncheck;
++legalmoveindex;
++columncheck;
}
else
{
++columncheck;
}
arrayoflegalmoves = realloc(arrayoflegalmoves, (legalmoveindex) * sizeof(int));
}
has a realloc inside of it. The realloc should be moved to immediately outside of it, like so
while (columncheck <= columns - 1)
{
if (spaces[columncheck][0] == 0)
{
arrayoflegalmoves[legalmoveindex] = columncheck;
++legalmoveindex;
++columncheck;
}
else
{
++columncheck;
}
}
arrayoflegalmoves = realloc(arrayoflegalmoves, (legalmoveindex) * sizeof(int));
it is unusual to have the columns be the first index in an array.
having the first index of an array be columns leads to confusion
// suggest using camel case for all variable names, for readability
Board *AllocateBoard(int columns, int rows)
{
int **array= malloc(sizeof(int *) *columns); // add check that malloc successful
int r = 0;
for ( r = 0; r < columns; ++r)
{
array[r] = malloc(sizeof(int) * rows); // <-- add: check that malloc successful
}
int j = columns - 1; // this results in last column not initialized
int k = rows - 1; // this results in last row of each column not initialized
int m = 0; // column loop counter
int n = 0; // row loop counter
for ( m = 0; m < j; ++m)
{
for ( n = 0; n < k; ++n)
{
array[m][n] = 0;
}
}
Board *board = malloc(sizeof(Board)); // <-- add: check if malloc successful
board->columns = columns;
board->rows = rows;
board->spaces = array;
return board;
} // end function: AllocateBoard
// why is this only looking at the first row of each column?
int computerMakeMove(Board *board)
{
int RandIndex = 0;
int **spaces = board->spaces;
int columns = board->columns;
int *arrayoflegalmoves = malloc(sizeof(int) * (columns)); // <-- add check that malloc successful
int columncheck = 0;
int legalmoveindex = 0;
while (columncheck <= columns - 1)// should be: for(; columncheck < columns; columncheck++ )
{
if (spaces[columncheck][0] == 0)
{ // then first row of column is zero
arrayoflegalmoves[legalmoveindex] = columncheck;
++legalmoveindex;
++columncheck; // <-- remove this line
}
else // remove this 'else' code block
{
++columncheck;
} // end if
arrayoflegalmoves = realloc(arrayoflegalmoves, (legalmoveindex) * sizeof(int));
// <-- 1) use temp int*, in case realloc fails
// <-- 2) if realloc successful, update arrayoflegalmoves
// <-- 3) the code is not checking each row of each column,
// so the original malloc is more than plenty
// so why bother to realloc
// <-- 4) if legalmoveindex is 0 then realloc returns NULL
} // end while
// in following, what about when zero moves found? probably should return NULL
if (legalmoveindex == 1)
{ // only one column[row0] found to contain 0
return arrayoflegalmoves[0];
}
else
{
RandIndex = rand() % (legalmoveindex);
return arrayoflegalmoves[RandIndex]; // if zero moves found, this returns a
// de-reference to address 0
// which would result in a seg fault event
} // end if
} // end function: computerMakeMove

reallocating size of array gives me no change

I'm trying to realloc the size of my array but it doesn't change. I can separate it to two issues:
Coordinate *closeCoordinatesArray = malloc(sizeof(Coordinate) * 0);
Coordinate nextCoordinate = coordinatesMainArray[nextCoordinateIndex];
for (int p = 0; p < 4; p++) {
switch (p) {
case 0:
if (((nextCoordinate.x - 1) >= 0) && ((nextCoordinate.y - 1) >= 0)) {
int sizeOfArray = sizeof(*closeCoordinatesArray);
int sizeOfFirstObject = sizeof(closeCoordinatesArray[0]);
int closeCoordinatesArrayLength = (sizeOfArray / sizeOfFirstObject);
closeCoordinatesArray = realloc(closeCoordinatesArray,sizeof(Coordinate) * (closeCoordinatesArrayLength + 1));
sizeOfArray = sizeof(*closeCoordinatesArray);
sizeOfFirstObject = sizeof(closeCoordinatesArray[0]);
closeCoordinatesArrayLength = (sizeOfArray / sizeOfFirstObject);
After i malloc it in the first row, it shows that its length is 1. I would assume it should be 0 (i want it to be 0).
After a realloc it in case 0 I check the length and it's still 1.
What am i doing wrong?
It's important to remember that sizeof is evaluated at compile time; therefore it could not know about a variable length array. All it gives you is the size of the implicit pointer associated with the array. (Remember that in C pointers and arrays are equivalent).

Resources