0

So I was trying to pormpt the user to type in a number, and then store that value in a dynamic array. Here is the code first:

#include <stdio.h>
#include <stdlib.h>
//dynamically grow the array 
void growArray(int *arr, int *size){
 //double the size of the array
 printf("Resizing array\n");
 int *temp = malloc( *size * 2 * sizeof(int)); 
 printf("Malloc was succesfuly\n");
 int i; 
 for (i = 0; i < *size; i++)
 temp[i] = arr[i]; 
 printf("About to free arr\n");
 printf("arr: %p", arr); 
 printf("temp: %p", temp);
 free(arr);
 arr = malloc( *size * 2 * sizeof(int)); 
 printf("About to change value to arr\n");
 arr = temp; 
 free(temp);
 printf("About to change the value of size\n");
 *size *= 2; 
 printf("New size: %d\n", *size);
}
int main(){
 int *dynamicArr; 
 int *size; 
 *size = 1; 
 dynamicArr = (int*) malloc(sizeof(int));
 int value, i;
 i = 0; 
 do{
 printf("\nPlease enter in a int value: ");
 scanf("%d", &value); 
 //check if the array needs to be resizesd;
 printf("Checking if size if sufficient\n");
 if (i >= *size)
 growArray(dynamicArr, size);
 if (value != -999){
 printf("Adding value to the array\n");
 dynamicArr[i] = value;
 i ++; 
 }
 }while(value != -999); 
 for (i = 0; i < *size; i++){
 printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
 }
 return 0; 
}

As you can see, I have a bunch of print statements, that I so I can see at what point my program is at, and what it is current doing. So, the program initially works. I am able to add in 8 values successfully (and resize the array 3 times, going from size 1 to size 8). But when I add in my 9 value, it has to resize the array, in which the method growArray() is called. But, for some reason I get the following error:

*** Error in `./a.out': free(): invalid next size (fast): 0x0000000000e69010 ***
Segmentation fault (core dumped)

Before the error, the printf("About to free arr") works, but printf("arr: %p", arr); isn't called.

I have no idea why this is happening, some help would be much appreciated.

asked Sep 9, 2017 at 20:45
17
  • 1) int *size; *size = 1; --> int size = 1;.. growArray(dynamicArr, size); --> growArray(dynamicArr, &size); Commented Sep 9, 2017 at 20:48
  • 2) void growArray(int *arr, int *size) --> void growArray(int **arr, int *size) or int *growArray(int *arr, int *size) (return new array) You can also use realloc instead. Commented Sep 9, 2017 at 20:49
  • 3) arr = malloc( *size * 2 * sizeof(int)); occurs memory leak. Commented Sep 9, 2017 at 20:52
  • 4) arr = temp; free(temp); Do not free here.--> arr = temp; Commented Sep 9, 2017 at 20:52
  • There are errors in the code as @BLUEPIXY commented, but you should just use realloc to double you array. Commented Sep 9, 2017 at 20:54

2 Answers 2

2

You code should probably look more like this:

#include <stdio.h>
#include <stdlib.h>
int main() {
 int size = 1;
 int *dynamicArr = malloc(size * sizeof(*dynamicArr));
 int idx = 0;
 while (1) {
 int value;
 printf("\nPlease enter in a int value: ");
 scanf("%d", &value);
 if (value == -999) {
 break;
 }
 //check if the array needs to be resizesd
 printf("Checking if size if sufficient\n");
 if (idx >= size) {
 size *= 2;
 dynamicArr = realloc(dynamicArr, size * sizeof(*dynamicArr));
 }
 printf("Adding value to the array\n");
 dynamicArr[idx++] = value;
 }
 int i;
 for (i = 0; i < idx; i++) {
 printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
 }
 free(dynamicArr);
 return 0; 
}

Or if you want to stick with your implementation:

#include <stdio.h>
#include <stdlib.h>
//dynamically grow the array 
void growArray(int **arr, int *size){
 //double the size of the array
 printf("Resizing array\n");
 int *temp = malloc( *size * 2 * sizeof(int)); 
 printf("Malloc was succesfuly\n");
 int i;
 for (i = 0; i < *size; i++)
 temp[i] = (*arr)[i];
 printf("About to free arr\n");
 printf("arr: %p\n", *arr); 
 printf("temp: %p\n", temp);
 free(*arr);
 printf("About to change value to arr\n");
 *arr = temp;
 printf("About to change the value of size\n");
 *size *= 2;
 printf("New size: %d\n", *size);
}
int main() {
 int size = 1;
 int *dynamicArr = malloc(size * sizeof(*dynamicArr));
 int idx = 0;
 while (1) {
 int value;
 printf("\nPlease enter in a int value: ");
 scanf("%d", &value);
 if (value == -999) {
 break;
 }
 //check if the array needs to be resizesd;
 printf("Checking if size if sufficient\n");
 if (idx >= size) {
 growArray(&dynamicArr, &size);
 }
 printf("Adding value to the array\n");
 dynamicArr[idx++] = value;
 }
 int i;
 for (i = 0; i < idx; i++){
 printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
 }
 free(dynamicArr);
 return 0; 
}

BTW, you can use memcpy to copy the whole existing array to the temp array.

answered Sep 9, 2017 at 21:03
Sign up to request clarification or add additional context in comments.

5 Comments

I appreciate your answer, but I have to use malloc, since that is the current focus of the course (for right now).
@VineetPatel I added your code with corrections to the answer
IT WORKED! Thanks a lot. But why does it work? Why should have I used a double pointer?
@VineetPatel The same reason you used a pointer for size. You want to changes to be visible to the calling function. You allocate new space in temp, which means you get a new address. You then want the calling function to know that the new larger "array" starts there, so you must pass a pointer to the variable which stored the last address, a.k.a dynamicArr, so you should pass &dynamicArr. only that way you could make changes to the value stored in it (the value, in this case, is the address where the array starts)
do NOT assign the returned pointer from realloc() directly to the target variable. Because if realloc() fails, then the original pointer is lost, resulting in a memory leak. always use a 'temp' variable for the initial assignment, then check (!=NULL) and only if not NULL then assign tot he target variable. AND if that pointer is dereferenced when realloc() failed, then the program will be trying to access address 0 (from the NULL returned from realloc()) which will result in a seg fault event.
1

There are a couple of problems in your original code.

(a) The parameter arr is passed to growArray by value, so your assignments arr = malloc(...) and arr = temp are not updating the variable referenced in main() only the copy that is local to growArray. On the other hand, when you call free(arr) you are freeing the buffer pointed to by the variable dynamicArr in main(). This is the immediate cause of your segfault.

(b) When you assign arr = temp then free(temp); you leak the buffer you malloc()ed just above, then free the buffer you assigned arr to point to (leaving it dangling).

void growArray(int *arr, int *size){

When entering growArray, arr points to a buffer, A

 ...
 int *temp = malloc( *size * 2 * sizeof(int));

temp is initialized to point to a new buffer, B

 ...
 free(arr);

the original buffer, A, is freed. The local variable arr is now a dangling pointer, as is whatever pointer the caller holds that was passed into this routine by value.

 arr = malloc( *size * 2 * sizeof(int)); 

arr is set to a freshly allocated buffer, C.

 ...
 arr = temp; 

arr is set to alias temp, pointing to the buffer B. The buffer C is leaked.

 free(temp);

Buffer B, pointed to by both temp and arr is freed. They are both now dangling pointers. When arr is later

 ...
}

Both tmp and arr go out of scope. The buffers B and C are leaked.

int main(){
 int *dynamicArr; 
 int *size; 
 *size = 1; 
 dynamicArr = (int*) malloc(sizeof(int));

dynamicArr points to a malloced buffer ... do{ ... if(...){ growArray(dynamicArr, size); ... }

The first time this if condition passes, the value of dynamicArr is passed as the argument arr to growArray. growArray frees the buffer it points to and then allocs and leaks some memory without affecting the local value of dynamicArr. dynamicArr is now a dangling pointer.

 if (value != -999){
 ...
 dynamicArr[i] = value;

And then this accesses the dangling pointer and segfaults.

answered Sep 10, 2017 at 0:52

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.