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

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.

Related

i'm getting unexpected behavior using realloc

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];
}
}

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.

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

using malloc() for double pointers

a malloc question.
First, I generate some strings.
And second, I allocate none-space for copying pointers which point to those strings.
At this moment the program should probably crash, since I ve tried to copy those pointers to nowhere, but it doesn’t crash. How is it possible?
Any comments would be appreciated.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i,
iJ,
iCharCount = 0,
iCharVal,
iStrLen = 0,
iStrNum = 50,
iStrCount = 0,
iAllocSize = 0;
char *pcStr,
*pcStr_CurPos,
**ppcStr,
**ppcStr_CurPos;
// suppose, an average length of string is * N bytes.
iAllocSize = iStrNum * 6;
iStrCount = 0;
// allocate ...
pcStr = pcStr_CurPos = (char*) malloc (iAllocSize);
if (pcStr==NULL){printf("NULL == malloc()\n"); exit (1);}
for (i=0; i < iStrNum; i++)
{
iStrCount++;
iStrLen = rand() % 7 + 2; // is in the range 2 to 8
printf("Len of Str=%d; str=[", iStrLen);
for (iJ = 0; iJ < iStrLen-1; iJ++)
{
// A-Z a-z
iCharVal = rand() % 58 + 65;
if (iCharVal > 90 && iCharVal < 97) {iJ--; continue;}
if (pcStr_CurPos < pcStr + iAllocSize )
{
printf ("%c", iCharVal);
*pcStr_CurPos++ = iCharVal;
iCharCount ++;
}
else
{
*pcStr_CurPos++ = 0;
iCharCount ++;
printf ("]\n");
goto exit;
}
}
printf ("]\n");
*pcStr_CurPos++ = 0;
iCharCount ++;
}
exit:
// I allocate NOTHING, ...
ppcStr = ppcStr_CurPos = (char**) malloc (0); // ZERO !
// Copying pointers ...
pcStr_CurPos = pcStr;
while(pcStr_CurPos < pcStr + iCharCount)
{
//... BUT IT WORKS AND DON'T CRASH.
// HOW IS IT POSSIBLE ???
*ppcStr_CurPos++ = pcStr_CurPos;
while (*pcStr_CurPos++) ;
}
ppcStr_CurPos = ppcStr;
iStrNum = iStrCount;
printf ("\n Output ppcStr:\n", iCharCount );
while(iStrNum--)
{
printf("[%d][%s]\n", iStrNum, *(ppcStr_CurPos++));
}
printf ("Press Enter key or sth\n");
getchar();
return 0;
}
In general, C is not guaranteed to crash if you access uninitialized memory. The behavior is undefined, which means anything could happen. The compiler could make demons fly out of your nose, as they say.
I believe that in practice the system may allocate more memory than you requested. So here
ppcStr = ppcStr_CurPos = (char**) malloc (0); // ZERO !
the actual size of the block may be 1 or more:
If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
Thus if the returned pointer is not null, it may point to a buffer of nonzero length.
Then here
pcStr_CurPos = pcStr;
while(pcStr_CurPos < pcStr + iCharCount)
{
//... BUT IT WORKS AND DON'T CRASH.
// HOW IS IT POSSIBLE ???
*ppcStr_CurPos++ = pcStr_CurPos;
while (*pcStr_CurPos++) ;
}
after copying the 1st byte into the "0 byte" buffer, in the inner while you seem to be stepping pcStr_CurPos through till the end of the string it points to, then consequently exit from the outer loop. Thus no more bytes are copied!
So I would venture to say that in practice you didn't necessarily write to unallocated memory (although according to the above quote it is still undefined behaviour to write to that buffer - but as #novalis rightly pointed out, undefined behaviour may not necessarily result in a crash).

Reallocate a 2d char array

I have following code
int wordLenght = 256, arrayLength = 2, i = 0, counter = 0;
char **stringArray = NULL;
stringArray = calloc(arrayLength, sizeof(*stringArray));
for(counter; counter<wordLenght; counter++)
stringArray[counter] = calloc(wordLenght, sizeof(stringArray));
while(1)
{
printf("Input: ");
fgets(stringArray[i], wordLenght, stdin);
printf("stringArray[%d]: %s\n", i, stringArray[i]);
if(i == arrayLength)
{
printf("Reallocation !!!\n");
arrayLength *= 2;
stringArray = realloc(stringArray, arrayLength*sizeof(*stringArray));
}
i++;
}
I get this reallocation error:
*** glibc detected *** ./stringArray: realloc(): invalid next size: 0x0000000000b49010 ***
======= Backtrace: =========
/lib/libc.so.6(+0x775b6)[0x7f4dd12565b6]
/lib/libc.so.6(+0x7dd66)[0x7f4dd125cd66]
/lib/libc.so.6(realloc+0xf0)[0x7f4dd125d080]
./stringArray[0x4007f9]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f4dd11fdc4d]
./stringArray[0x400629]
What's my problem here ???
Thanks, greets
stringArray = calloc(arrayLength, sizeof(*stringArray));
Here you probably wanted to use sizeof(char*)
for(counter; counter<wordLenght; counter++) stringArray[counter] = calloc(wordLenght, sizeof(stringArray));
Here you are looping 256 times (wordLenght) but you should only 2 times (arrayLength). Additionally you probably wanted to use sizeof(char) instead of sizeof(stringArray).
if(i == arrayLength) {...}
This check should be done before you call fgets, because right now you are firstly using memory and later allocate them.
Additionally after you reallocate stringArray you need to allocate rest of strings using something like this
for(counter = i; counter<arrayLength; counter++) stringArray[counter] = (char*)calloc(wordLenght, sizeof(char));
And finally you need to free all allocated memory before you exit application.
You probably didn't mean sizeof(*stringArray)
In fact I believe you may want to relook at the calloc call too, I think you are allocating the size of the pointer there (word length times).
After the first time this line executes:
stringArray = realloc(stringArray, arrayLength*sizeof(*stringArray));
then stringArray[arrayLength/2] will be a garbage value - you haven't set it to point to storage for the word.
This part should use either use sizeof(**stringArray), or 1 as **stringArray is char, and the counter should only go up to arrayLength:
for(counter; counter<wordLenght; counter++)
stringArray[counter] = calloc(wordLenght, sizeof(stringArray));
Instead allocate in one block:
char* block = malloc(wordLength * arrayLength);
for ( counter; counter < arrayLength; ++counter )
stringArray[counter] = block + ( counter * wordLength );
At the moment, it's possible that there is some space after stringArray, into which you are storing the (wordLength-arrayLength) extra pointers when you calloc them, and realloc doesn't move stringArray.
It's quite probable that 0xb49010 is one of the pointers you calloc'd, and you're overwritten the memory where malloc keeps its block size..
But since you're writing off the end of stringArray, you're into undefined behaviour anyway.
Ok here is the whole solution:
int wordLength = 256, arrayLength = 2, i = 0, counter = 0;
char **stringArray = NULL;
char buffer[wordLength];
stringArray = calloc(arrayLength, sizeof(char*));
for(counter; counter<arrayLength; counter++) stringArray[counter] = (char*)calloc(wordLength, sizeof(char));
while(1)
{
if(i == arrayLength)
{
printf("Reallocation !!!\n");
arrayLength *= 2;
stringArray = realloc(stringArray, arrayLength*sizeof(char*));
for(counter = i; counter<arrayLength; counter++) stringArray[counter] = (char*)calloc(wordLength, sizeof(char));
}
printf("Input: ");
fgets(buffer, wordLength, stdin);
if(!strcmp(buffer,"q\n")) break; // also free here
else stringArray[i] = buffer;
printf("stringArray[%d]: %s\n", i, stringArray[i]);
i++;
}
How is the best way to free the space ?!

Resources