I am using dynamic memory allocation in C for a simple problem that I am trying to solve. It involves taking user input for the elements of 2 arrays. I was thinking that I will initialise the array to a large size and use realloc to reduce the size once the input has been completed. ?below is the code for same:
void arrayop()
{
int val, i=0;
int *arr1 = (int*) calloc(100,sizeof(int));
int *arr2 = (int*) calloc(100,sizeof(int));
printf("Enter first array:(-1 to stop)\n");
while(val!=-1)
{
if(val != -1)
{
scanf("%d",&val);
*(arr1 + i) = val;
i++;
}
}
//printf("\t%d\n",i);
arr1 = (int*)realloc(arr1,(i));
//printf("\t%d\n",(sizeof(arr1)));
for(int j=0;j<i;j++)
{
printf("%d ",*(arr1 + j));
}
printf("\n");
}
However, realloc() is somehow overwriting already entered elements and filling them with garbage value. Can anyone give me any insight as to why this is happening, or where I am wrong?
realloc expects the allocation size, but you're telling it how many ints you want. When you call it like this:
arr1 = (int*)realloc(arr1,(i));
i holds the number of ints that you want to allocate space for, but the actual size needed for the allocation is i * sizeof(int), so to fix it you need:
arr1 = realloc(arr1, sizeof(int) * i);
Or, even better:
arr1 = realloc(arr1, sizeof(*arr1) * i);
The second variant will work even if you change the type of arr1 from int * to, say, short *.
You may also want to check the pointer returned by realloc and make sure the allocation succeeded. Note that if realloc fails, arr1 won't be freed and you'll end up leaking it. A better approach is:
int *temp = realloc(arr1, sizeof(*arr1) * i);
if (temp == NULL)
{
fprintf(stderr, "realloc failed\n");
free(arr1);
return;
}
arr1 = temp;
While we're at it, don't cast the result of malloc, calloc, or realloc. See Do I cast the result of malloc?
.
Related
I'm struggling with a C struct which must hold a dynamic array of smaller structs:
typedef struct issueStruct {
int data;
} issue;
typedef struct volumeStruct {
issue* collection;
size_t elements;
} volume;
I can dynamically create as many issue structs as I like within a volume struct's array. I can also iterate through that array:
int main(){
volume* TimeMagazine = (volume*)malloc(sizeof(volume));
TimeMagazine->collection = (issue*)malloc(4 * sizeof(issue));
TimeMagazine->elements = 4;
issue* ptr = TimeMagazine->collection;
int i;
// Populate & iterate through array:
i = 0;
while(i < TimeMagazine->elements){
ptr->data = 100*i;
printf("%d) %d\n", i, ptr->data);
i++;
ptr = ptr+i; // Advance ptr
}
return 0;
}
OUTPUT:
[Linux]$ gcc -Wall magazines.c
[Linux]$ ./a.out
0) 0
1) 100
2) 200
3) 300
[Linux]$
So far, so good. When I step through the above in GDB, everything looks okay, although I notice that the issue structs do not seem to have contiguous memory addresses. Here's the memory addresses I saw:
issue 0) 0x602030
issue 1) 0x602034
issue 2) 0x60203c
issue 3) 0x602048
That gave me some pause; I would have assumed all issues would be 4 bytes apart, as sizeof(issue) = 4. More seriously, when I modify my "iterate through" code to free up the elements of the array, my code seg faults. Specifically, it faults when it tries to free the second issue. Here's the code:
i = 0;
ptr = TimeMagazine->collection;
issue* ptr2 = ptr;
while(i< TimeMagazine->elements){
printf("freeing %d...\n", i);
i++;
free(ptr2); // free ptr2
ptr2 = ptr = ptr+i; // advance ptr & ptr2
}
Here's the error (GCC on Linux):
*** Error in `./a.out': free(): invalid pointer: 0x000000000137c034 ***
So I'm sure I'm missing something here, but not sure what. Can someone recommend an effective way to free() the array elements?
Many thanks!
-Pete
PS - There are a lot of "freeing structs in array" posts, but none seemed to precisely match what I am doing. So I am posting this in the hope that my version of this question is unique.
while(i < TimeMagazine->elements){
ptr->data = 100*i;
printf("%d) %d\n", i, ptr->data);
i++;
ptr = ptr+i; // Advance ptr
}
You are using wrong pointer arithmetic in ptr = ptr+i, should be ptr = ptr+1 or you access outside of the bounds. Same for the free section.
And as pointed out by #kaylum in comments: you are calling free in a loop, this is also wrong, you can free(TimeMagazine->collection); at once since you are reserving space for 4 elements in the same block.
This is a side note regarding contiguous memory and structs containing dynamic arrays. For the actual answer refer to the answer given by #KeineLust.
As mentioned before, one malloc == one free.
However, unmentioned is the fact that contiguous memory often performs better due to caching considerations.
This means that your struct volumeStruct would perform better if both it's memory and the dynamic array were allocated using the same malloc call.
There are two common ways to accomplish this.
One, using the same structures you currently have (I fixed your loop to have ptr = ptr + 1, so we don't go out of bounds):
int main(){
volume* TimeMagazine = (volume*)malloc(sizeof(volume) + (4 * sizeof(issue)) );
TimeMagazine->collection = TimeMagazine + 1; // pointer arithmetics
TimeMagazine->elements = 4;
issue* ptr = TimeMagazine->collection;
int i;
// Populate & iterate through array:
i = 0;
while(i < TimeMagazine->elements){
ptr->data = 100*i;
printf("%d) %d\n", i, ptr->data);
i++;
ptr = ptr+1; // Advance ptr
}
free(TimeMagazine);
return 0;
}
Another option (I think this was introduced in C99), is to add a variable length array at the end of the struct. This saves you the 8 (or 4) bytes required for the collection pointer.
i.e.:
typedef struct issueStruct {
int data;
} issue;
typedef struct volumeStruct {
size_t elements;
issue collection[];
} volume;
int main(){
volume* TimeMagazine = (volume*)malloc(sizeof(volume) + (4 * sizeof(issue)) );
TimeMagazine->elements = 4;
// no need to assign a value for TimeMagazine->collection
issue* ptr = TimeMagazine->collection;
int i;
// Populate & iterate through array:
i = 0;
while(i < TimeMagazine->elements){
ptr->data = 100*i;
printf("%d) %d\n", i, ptr->data);
i++;
ptr = ptr+1; // Advance ptr
}
free(TimeMagazine);
return 0;
}
The big upside is CPU memory caching and simpler code. The fact that we're saving two system calls per object (one malloc and one free) is irrelevant in most cases.
I have a file which stored a sequence of integers. The number of total integers is unknown, so I keep using malloc() to apply new memory if i read an integer from the file.
I don't know if i could keep asking for memory and add them at the end of the array. The Xcode keeps warning me that 'EXC_BAD_EXCESS' in the line of malloc().
How could i do this if i keep reading integers from a file?
int main()
{
//1.read from file
int *a = NULL;
int size=0;
//char ch;
FILE *in;
//open file
if ( (in=fopen("/Users/NUO/Desktop/in.text","r")) == NULL){
printf("cannot open input file\n");
exit(0); //if file open fail, stop the program
}
while( ! feof(in) ){
a = (int *)malloc(sizeof(int));
fscanf(in,"%d", &a[size] );;
printf("a[i]=%d\n",a[size]);
size++;
}
fclose(in);
return 0;
}
Calling malloc() repeatedly like that doesn't do what you think it does. Each time malloc(sizeof(int)) is called, it allocates a separate, new block of memory that's only large enough for one integer. Writing to a[size] ends up writing off the end of that array for every value past the first one.
What you want here is the realloc() function, e.g.
a = realloc(a, sizeof(int) * (size + 1));
if (a == NULL) { ... handle error ... }
Reworking your code such that size is actually the size of the array, rather than its last index, would help simplify this code, but that's neither here nor there.
Instead of using malloc, use realloc.
Don't use feof(in) in a while loop. See why.
int number;
while( fscanf(in, "%d", &number) == 1 ){
a = realloc(a, sizeof(int)*(size+1));
if ( a == NULL )
{
// Problem.
exit(0);
}
a[size] = number;
printf("a[i]=%d\n", a[size]);
size++;
}
Your malloc() is overwriting your previous storage with just enough space for a single integer!
a = (int *)malloc(sizeof(int));
^^^ assignment overwrites what you have stored!
Instead, realloc() the array:
a = realloc(a, sizeof(int)*(size+1));
You haven't allocated an array of integers, you've allocated one integer here. So you'll need to allocate a default array size, then resize if you're about to over run. This will resize it by 2 each time it is full. Might not be in your best interest to resize it this way, but you could also reallocate each for each additional field.
size_t size = 0;
size_t current_size = 2;
a = (int *)malloc(sizeof(int) * current_size);
if(!a)
handle_error();
while( ! feof(in) ){
if(size >= current_size) {
current_size *= 2;
a = (int *)realloc(a, sizeof(int) * current_size);
if(!a)
handle_error();
}
fscanf(in,"%d", &a[size] );;
printf("a[i]=%d\n",a[size]);
size++;
}
The usual approach is to allocate some amount of space at first (large enough to cover most of your cases), then double it as necessary, using the realloc function.
An example:
#define INITIAL_ALLOCATED 32 // or enough to cover most cases
...
size_t allocated = INITIAL_ALLOCATED;
size_t size = 0;
...
int *a = malloc( sizeof *a * allocated );
if ( !a )
// panic
int val;
while ( fscanf( in, "%d", &val ) == 1 )
{
if ( size == allocated )
{
int *tmp = realloc( a, sizeof *a * allocated * 2 ); // double the size of the buffer
if ( tmp )
{
a = tmp;
allocated *= 2;
}
else
{
// realloc failed - you can treat this as a fatal error, or you
// can give the user a choice to continue with the data that's
// been read so far.
}
a[size++] = val;
}
}
We start by allocating 32 elements to a. Then we read a value from the file. If we're not at the end of the array (size is not equal to allocated), we add that value to the end of the array. If we are at the end of the array, we then double the size of it using realloc. If the realloc call succeeds, we update the allocated variable to keep track of the new size and add the value to the array. We keep going until we reach the end of the input file.
Doubling the size of the array each time we reach the limit reduces the total number of realloc calls, which can save performance if you're loading a lot of values.
Note that I assigned the result of realloc to a different variable tmp. realloc will return NULL if it cannot extend the array for any reason. If we assign that NULL value to a, we lose our reference to the memory that was allocated before, causing a memory leak.
Note also that we check the result of fscanf instead of calling feof, since feof won't return true until after we've already tried to read past the end of the file.
For whatever reason I am getting the following error when trying to free the 2D array I created:
Error in `./a.out': free(): invalid next size (fast): 0x0000000001759310 *** Aborted (core dumped)
I printed out the contents of the array and they are correct and I am able access all of the elements. However, I am yet to be able to free it. The error occurs when going through the freeing loop, i.e. freeing double *. Would appreciate any help.
Thanks!
Here is the code:
/*allocation*/
double **block_mat = (double **) malloc (sizeof(double *) * num_blocks);
int i;
for (i = 0; i <num_blocks; i++){
block_mat[i] = (double *) malloc (sizeof(double) * s);
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
free(block_mat);
EDIT:
The error was found! I under-allocated memory...So when I printed out my arrays they looked like everything was fine... I allocated arrays of sizes s, but used s^2 instead. Thank you everyone!
You allocate space for s doubles for each block_mat[i]. Later, you access
block_mat[i][block_index] = 0;
block_index++;
but you never check that block_index goes out of bounds, which it does.
If you write beyond the s allocated doubles, you might corrupt the internal control data for the subsequent pointer, which usually is placed before the pointer returned by malloc and which is required to be intact by free.
Are you sure that these pointers were all allocated with distinct mallocs?
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
free(block_mat);
If two of them are the same pointer, then you are trying to free something twice.
This is incorrect:
free(my_matrix);
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
The order should be at least like this:
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
You have several problem that can impact allocation. The first, what if the call to strtol fails?
s = (int)strtol(argv [3], &ptr, 10);
You should check the conversion:
#include <errno.h>
...
else {
errno = 0;
long tmp = strtol(argv [3], &ptr, 10);
if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
(errno != 0 && tmp == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (ptr == argv[3]) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
s = (int)tmp;
}
Next, with your allocation and free, you were on the right track, but don't cast the return of malloc. Casting the return only increases the chance of a hard to debug error. When allocating a pointer-to-pointer-to-double, you need to allocate as many pointers as needed. (num_blocks) in your case. When computing the size of the allocation, you can simply dereference the variable being allocated which again lessens the chance of error:
int i;
double **block_mat = malloc (sizeof *block_mat * num_blocks);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = malloc (sizeof **block_mat * s);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
Note: you must initialize all values in block_mat before you begin referencing the elements to prevent the deference of an unassigned value later. (e.g. double result = block_mat[i][j] * Pi;) Consider adding:
block_mat[i] = malloc (sizeof **block_mat * s);
/* check for failure */
block_mat[i] = 0.0;
Note: When allocating numerical matricies, consider using calloc instead of malloc as it will initialize all values to '0' and prevent the inadvertent dereference of an unassigned valued -- which is undefined behavior. Using calloc you would have:
int i;
double **block_mat = calloc (num_blocks, sizeof *block_mat);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = calloc (s, sizeof **block_mat);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
Note: when s is greater than 1, you will alloc space for more than one double at each pointer. Noting prevents you from doing that, but you are responsible for handling the offset to each value. (e.g. result = *(block_mat[i] + j + n * sizeof **block_mat) * Pi;, where n is 0 <= n < s) If you are storing multiple doubles in each pointer, consider using a pointer-to-struct instead. E.g.:
typedef struct point {
double x;
double y;
double z;
} point;
This question already has an answer here:
free char*: invalid next size (fast) [duplicate]
(1 answer)
Closed 8 years ago.
I know there are tons of other realloc questions and answers and I have read almost all of them, but I still couldn't manage to fix my problem.
I decided to stop trying when I accidentaly discovered a very strange behaviour of my code.
I introduced a line to try something, but although I don't use the value of newElems in main, the line changes the behaviour.
When the line is commented, the code fails at first realloc. Including the line, the first realloc works. (it still crashes on the second one).
Any ideas on what might be happening?
int main(int argc, char** argv) {
Pqueue q = pqueue_new(3);
Node a = {.name = "a"}, b = {.name = "b"},
c = {.name = "c"}, d = {.name = "d"};
push(& q, & a, 3);
// the next one is the strange line: as you can see, it doesn't modify q
// but commenting it out produces different behaviour
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
push(& q, & b, 5);
push(& q, & c, 4);
char s[5];
Node* n;
for (int i = 1; i <= 65; ++i) {
sprintf(s, "%d", i);
n = malloc(sizeof *n);
n->name = strdup(s);
push(& q, n, i);
}
Node* current = NULL;
while ((current = pop(& q))) {
printf("%s ", current->name);
}
return 0;
}
and the push function:
void push(Pqueue* q, Node* item, int priority) {
if (q->size >= q->capacity) {
if (DEBUG)
fprintf(stderr, "Reallocating bigger queue from capacity %d\n",
q->capacity);
q->capacity *= 2;
Pqueue_elem* newElems = realloc(q->elems,
q->capacity * sizeof *newElems);
check(newElems, "a bigger elems array");
q->elems = newElems;
}
// append at the end, then find its correct place and move it there
int idx = ++q->size, p;
while ((p = PARENT(idx)) && priority > q->elems[p].priority) {
q->elems[idx] = q->elems[p];
idx = p;
}
// after exiting the while, idx is at the right place for the element
q->elems[idx].data = item;
q->elems[idx].priority = priority;
}
The pqueue_new function:
Pqueue pqueue_new(unsigned int size) {
if (size < 4)
size = 4;
Pqueue* q = malloc(sizeof *q);
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
return *q;
}
realloc will change the amount of memory that is allocated, if needed. It is also free to move the data to another place in memory if that's more efficient (avoiding memory fragmentation).
The function, then, returns a new pointer to the new location in memory where your data is hiding. You're calling realloc, and allocating (probably) four times as much memory as before, so it's very likely that that allocated memory is situated elsewhere in memory.
In your comment, you said realloc works like free + malloc. Well, in some cases it can behave similarly, however: realloc and free are different functions, that do different tasks. Both are functions that manage the dynamic memory, so yes, obviously there are similarities, and in the case of realloc, sometimes they can seem to be doing the same thing, however: As I explained here, realloc and free are fundamentally different functions
However, by not assigning the return value of realloc to q.elems, you're left with a pointer to a memory address that is no longer valid. The rest of your program can, and probably does, exhibit signs of undefined behaviour, then.
Unless you show some more code, I suspect this will take care of the problem:
//change:
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
//to
q.elems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
Or better yet, check for NULL pointers:
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
if (newElems == NULL)
exit( EXIT_FAILURE );// + fprintf(stderr, "Fatal error...");
q.elems = newElems;//<-- assign new pointer!
Looking at your pqueue_new function, I would suggest a different approach. Have it return the pointer to Pqueue. You're working with a piece of dynamic memory, treat it accordingly, and have your code reflect that all the way through:
Pqueue * pqueue_new(size_t size)
{//size_t makes more sense
if (size < 4)
size = 4;
Pqueue* q = malloc(sizeof *q);
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
return q;
}
Alternatively, pass the function a pointer to a stack variable:
void pqueue_new(Pqueue *q, size_t size)
{
if (q == NULL)
{
fprintf(stderr, "pqueue_new does not do NULL pointers, I'm not Chuck Norris");
return;//or exit
}
if (size < 4)
size = 4;
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
}
//call like so:
int main ( void )
{
Pqueue q;
pqueue_new(&q, 3);
}
Those would be the more common approaches.
Thank you all for the suggestions! I wouldn't have solved it without them,
The strange behaviour was caused by an off by one error. I was reallocating the queue only when q->size >= q->capacity, but since q was indexed from 0, it meant that before realloc I was writing in a forbidden location (q->elems[q->size]), which messed everything up.
First of all I want to say that I did search around, but I didn't understand the solutions proposed to the existing questions.
Here is my question.
Array *create()
{
static Array *arr1;
void *arraypointer;
if ((arraypointer = (Array *) malloc(sizeof(Array))) == NULL) {
printf("Array not created because no memory is available. \n");
} else {
arraypointer = arr1;
printf("Array created successfully. \n");
}
return arr1;
}
I am assuming that that is good. Now, I want to add something to the array, so obviously I need to increase the size in memory. At the moment, I have this.
void add(Array S[], Item x)
{
static Array *arr1;
void *arraypointer;
arraypointer = (Array *) malloc(sizeof(Array) + 1);
if (is_element_of(x, S) == true) {
printf
("Item already exists in array and therefore it can't be added. \n");
} else {
strcpy(S->arr1[S->s].sinput, x.sinput);
S->arr1[S->s].iinput = x.iinput;
S->s++;
printf("Item added successfully. \n");
}
}
I feel this is not good, although I am not sure how I have to do it. The warning I get is that arr1 and arraypointer are not used in the Add method.
What should I do?
Thanks
P.S. I would appreciate if you keep it simple, as I am still trying to wrap my head around this malloc thing.
this is different from yours but It feel like the following
typedef int Item;
typedef struct da {
size_t s;//now size of array
Item *arr;//dynamic array
} Array;
Array *create(void){
Array *ap;
if((ap = malloc(sizeof(Array)))== NULL){
fprintf(stderr, "Array not created because no memory is available. \n");
} else {
fprintf(stderr, "Array created successfully. \n");
ap->s = 0;
ap->arr = NULL;
}
return ap;
}
bool is_equal(Item x, Item y){
return x == y;
}
bool is_element_of(Item x, Array *S){
size_t i;
for(i = 0; i < S->s ; ++i){
if(is_equal(x, S->arr[i]))
return true;
}
return false;
}
void add(Array *S, Item x){
if (is_element_of(x, S) == true){
fprintf(stderr, "Item already exists in array and therefore it can't be added. \n");
} else {
S->arr = realloc(S->arr, (S->s + 1) * sizeof(Item));
if(S->arr == NULL){
fprintf(stderr, "Memmory could not allocate.\n");
} else {
S->arr[S->s++] = x;
fprintf(stderr, "Item added successfully. \n");
}
}
}
Once you allocated memory with malloc and resize it afterwards, you'll have to use realloc. Otherwise, if you use malloc again you'll get a whole new array. Furthermore, if you forget to call free, you'll get a memory leak, b/c the "old" array is not freed. With realloc the content of your current array is preserved.
Also have a look at this related question: Differences between using realloc vs. free -> malloc functions
I am assuming that that is good.
No, it's not, sorry. Look at your code carefully: assuming malloc is successfull, first, it assigns a newly allocated memory region to arraypointer (which doesn't really have a reason to be void *, you should make it Array *), and then it assigns arr1 to arraypointer. After that, you just lost reference to the previously allocated block. Thus, your program contains a memory leak.
I don't see the point of using arr1, and I can't understand why you made it static. Why not something like this?
Array * create()
{
Array *arraypointer;
if ((arraypointer = malloc(sizeof(*arraypointer))) == NULL) {
printf("Array not created because no memory is available. \n");
} else {
printf("Array created successfully. \n");
}
return arraypointer;
}
The warning that you get inside add() is because you're not really using arr1 nor arraypointer: you're just using S. Nowhere in the function's code you use these variables. I'm guessing you will want to use realloc here, but it is hard to tell, since you didn't show us the structure definition for Array.