Reputation:
Can someone help me to write a program in C so as to create an infinite loop array?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int size;
int *a;
} array;
array* unbounded_create() {
array *x;
x->size = 64;
x = (array*)malloc(x->size*sizeof(array));
if(x==NULL) {
fprintf(stderr,"Could not allocate memory.\n");
abort();
}
return x;
}
void unbounded_destroy(array *a) {
free(a->a);
}
void unbounded_double(array *a) {
a = (array*)malloc(2*sizeof(array));
a->size *= 2;
}
void unbounded_set(array *a, int i, int value) {
while(i>a->size) {
unbounded_double(a);
}
a->a[i] = value;
}
int unbounded_get(array *a, int i){
while(i>a->size) {
unbounded_double(a);
}
return a->a[i];
}
int main() {
int i;
array *A = unbounded_create();
for(i=0;i<1000;i++)
unbounded_set(A,i,i);
for(i=0;i<1000;i++)
printf("%d", unbounded_get(A,i));
puts("");
unbounded_destroy(A);
return 0;
}
This is my code but compiler sends segmentation fault. Can someone explain why this happens?
Upvotes: 0
Views: 52
Reputation: 225767
You seem to be missing the fact that there's two things you need to allocate memory for:
Looking at unbounded_create
:
array *x;
x->size = 64;
x = (array*)malloc(x->size*sizeof(array));
You dereference x
before assigning it a value. That invokes undefined behavior which in this case causes a crash.
You then allocate memory to x
, but not the proper amount, and you never allocate memory to the a
member. You need sizeof(array)
bytes for the struct and x->size*sizeof(int)
for the array.
Now looking at unbounded_double
:
void unbounded_double(array *a) {
a = (array*)malloc(2*sizeof(array));
a->size *= 2;
}
You're throwing away the memory that was previously allocated for a
by overwriting it with newly allocated memory, and again you're not allocating the right amount. However, because the struct pointer was passed by value, the change is not reflected outside of the function, so all this does is leak memory.
You don't need to allocate space for the array
instance, but you do need to use realloc
on the a
member to expand its size and retain what was stored there previously.
Then in unbounded_destroy
:
void unbounded_destroy(array *a) {
free(a->a);
}
You never allocated space for a->a
but attempt to free it, and you don't free the space for a
. Once you fix the array creation, you need to free both.
With the above corrections in place, your code should look like this:
array* unbounded_create() {
array *x;
x = malloc(sizeof(array)); // don't cast the return value of malloc
if(x==NULL) {
fprintf(stderr,"Could not allocate memory.\n");
abort();
}
x->size = 64;
x->a = malloc(x->size*sizeof(int));
if(x->a==NULL) {
fprintf(stderr,"Could not allocate memory.\n");
abort();
}
return x;
}
void unbounded_destroy(array *a) {
free(a->a);
free(a);
}
void unbounded_double(array *a) {
a->a = realloc(2*a->size*sizeof(int));
if(a->a==NULL) {
fprintf(stderr,"Could not allocate memory.\n");
abort();
}
a->size *= 2;
}
Upvotes: 0
Reputation: 44368
Look at this:
array *x;
x->size = 64; // Here you dereference x but x is uninitialized
x = (array*)malloc(x->size*sizeof(array)); // Here you assign to x
So you use x
when it is uninitialized. This may cause seg fault.
...but compiler sends segmentation fault
Nitpick: No, the compiler doesn't send a seg fault. Seg fault happens at run-time. Not at compile-time.
Further - this:
void unbounded_double(array *a) {
a = (array*)malloc(2*sizeof(array));
a->size *= 2;
}
is not good. You can't change a
in the caller. You want something like:
void unbounded_double(array **a) { // Pointer to pointer
*a = malloc(2*sizeof(array));
(*a)->size *= 2;
}
Upvotes: 1