I am trying to dynamically create an array of rectangles with random values. However when trying to access the space I malloc I get a seg fault.
My Code:
typedef struct Point
{
double x;
double y;
} PointT;
typedef struct Rect
{
PointT location;
char color;
double w; //width
double h; //height
} RectT;
main()
{
RectT *recs;
randRect(&recs);
}
void randRect(RectT **rects)
{
int i;
rects =malloc(numRec*sizeof(RectT*));
for(i = 0; i < numRec-1; i++)
{
rects[i]->w=rand()%20;
rects[i]->h=rand()%20;
rects[i]->location.x=rand()%20;
rects[i]->location.y=rand()%20;
}
}
numRec is defined as 50
Rects in a function is a pointer to a pointer. So you need to allocate array of RectT items before using it. It should be like this:
void randRect(RectT **rects)
{
int i;
*rects =malloc(numRec*sizeof(RectT));
for(i = 0; i < numRec; i++)
{
(*rects)[i].w=rand()%20;
(*rects)[i].h=rand()%20;
(*rects)[i].location.x=rand()%20;
(*rects)[i].location.y=rand()%20;
}
}
Or even better way:
Rect* randRect()
{
int i;
Rect* rects =malloc(numRec*sizeof(RectT));
for(i = 0; i < numRec; i++)
{
rects[i].w=rand()%20;
rects[i].h=rand()%20;
rects[i].location.x=rand()%20;
rects[i].location.y=rand()%20;
}
return rects;
}
You allocate space for an array of RectT pointers, but you never allocate space for the RectTs that they point to.
You need to allocate space for rectangles, not for pointers to rectangles:
void randRect(RectT **rects) }
*rects = malloc(numRec * sizeof(RectT));
for (size_t i = 0; i != numRec; ++i) {
(*rects)[i]->w = 0; // etc
}
}
Related
I'm trying to create a function that creates a variable sized 2D funct array. I'm using the following code, which seems to work just fine on its own:
typedef struct
{
//Starter Properties
int TypeB;
int TypeF;
int TypeW;
//Randomized Properties
int RandB;
int RandF;
int RandW;
//Derived Properties
int Speed;
} MapTileData;
MapTileData **Map;
int i, x=5, y=5;
//Allocate Initial Space
Map = (MapTileData**)calloc(x, sizeof(MapTileData));
for(i = 0; i < x; i++)
{
Map[i] = (MapTileData*)calloc(y, sizeof(MapTileData));
}
So the above code creates a 2D struct array. My attempts to move the code to a function have been less successful, giving segmentation faults when trying to print the array:
void CreateMap(MapTileData **Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
Map = (MapTileData**)calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = (MapTileData*)calloc(ySize, sizeof(MapTileData));
}
}
Used in the code:
MapTileData **MapTile;
CreateMap(MapTile,5,5);
Any and all help is greatly appreciated!
Function arguments are passed by value in C and modifying arguments in callee won't affect caller's local variables.
Use pointers to modify caller's local variables.
void CreateMap(MapTileData ***Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
*Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
(*Map)[i] = calloc(ySize, sizeof(MapTileData));
}
}
Usage in the code:
MapTileData **MapTile;
CreateMap(&MapTile,5,5);
Alternate way: Pass the allocated array via the return value.
MapTileData **CreateMap(int xSize, int ySize)
{
//Variables
MapTileData **Map;
int i;
//Allocate Initial Space
Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = calloc(ySize, sizeof(MapTileData));
}
//Return the value
return Map;
}
Usage in the code:
MapTileData **MapTile;
Maptile = CreateMap(5,5);
Also note that they say you shouldn't cast the result of malloc() and its family in C.
#include <stdio.h>
#include <stdlib.h>
struct arrayADT {
int *A;
int size;
int length;
int *B;
int arr3;
};
struct arrayADT * MergeArray(struct arrayADT *arr1, struct arrayADT *arr2) { //we create thus in heap cuz we need to be able to use these in main function
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
int i, j, k;
i = j = k = 0;
while(i < arr1->length && j < arr1->length ) {
if(arr1->A[i] < arr2->A[j]) {
arr3->A[k] = arr1->A[i];
k++;
i++;
}
else {
arr3->A[k] = arr2->A[j];
k++;
j++;
}
}
for(; i<arr1->length ; i++) {
arr3->A[k] = arr1->A[i];
k++;
}
for(; j < arr2->length ; j++) {
arr3->A[k] = arr2->A[j];
k++;
}
arr3->length = arr1->length + arr2->length;
arr3->length = 10;
}
void main() {
struct arrayADT arr;
printf("Enter the size of an array");
scanf("%d", &arr.size);
arr.A = (struct arrayADT *)malloc(arr.size * sizeof(int));
arr.length = 0;
int n;
printf("enter the number of elements in an array");
scanf("%d", &n);
printf("enter the elements");
for(int i = 0; i < n; i++) {
scanf("%d", &arr.A[i]);
}
arr.length = n;
display(arr);
printf("Enter second array");
int j;
struct arrayADT *B = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
for(j = 0; j < arr.length; j++) {
scanf("%d", &B[j]);
}
struct arrayADT *arr3 = (struct arrayADT *)malloc(sizeof(struct arrayADT));
arr3 = MergeArray(&arr, &B);
display(*arr3);
I was looking to merge these arrays using heap memory and I am getting segmentation fault. I am new to C programming with pointers and I have been struck here it would be so helpful if I passed this barrier with your help.
And I am not getting where my error lies it would be helpful if someone specifies that too, so that I can avoid these errors in future.
PS: I am using minGW compiler.
In general, your code is rater unorganized. There are several cases for undefined behaviour, for example you don't scan in the second array correctly. The most probably candidate for your segmentaion fault is here:
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
This will give you an uninitialized chunk of memory. The length and size could of arr3 be anything, and its data field A does not point to valid memory. Accessing it will likely crash.
You have three arrays in your code. You construct each step by step and you treat each differently. That leads to errors easily. Let's go about this more systematically.
Let's create a struct type for a fixed-size array: The maximum size must be given on creation and cannot change. The actual length of the array may be anything from 0 to its maximum size.
typedef struct Array Array;
struct Array {
int *value; // data array
int length; // actual length, 0 <= length <= size
int size; // maximum capacity
};
We create such arrays on the heap and because initializing the members is error-prone, we write a constructor:
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
This function creates an empty array for at most size integers. If we allocate memory, we must de-allocate it later, so let's write a corresponding destructor function, which cleans up the ressources:
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
After destroying an array, it can no longer be used, just as with memory after calling free() on it.
The array is at first empty, so let's write a function to add elements at its end if there is room:
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
And a function to print it:
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
Now you can create arrays like so:
Array *a = array_create(10);
for (int i = 0; i < a->size; i++) {
array_push(a, i);
}
array_print(a);
array_destroy(a);
Your merge function will be simpler, too. Here's a full example. (But is uses generated array, not arrays typed in by the user.)
#include <stdio.h>
#include <stdlib.h>
typedef struct Array Array;
struct Array {
int *value;
int length;
int size;
};
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
Array *merge(Array *a, Array *b)
{
Array *res = array_create(a->length + b->length);
int i = 0;
int j = 0;
while(i < a->length && j < b->length) {
if(a->value[i] < b->value[j]) {
array_push(res, a->value[i++]);
} else {
array_push(res, b->value[j++]);
}
}
while(i < a->length) {
array_push(res, a->value[i++]);
}
while(j < b->length) {
array_push(res, b->value[j++]);
}
return res;
}
int main(void)
{
Array *a = array_create(10);
Array *b = array_create(6);
Array *c;
for (int i = 0; i < a->size; i++) {
array_push(a, 1 + 3 * i);
}
for (int i = 0; i < b->size; i++) {
array_push(b, 4 + 2 * i);
}
array_print(a);
array_print(b);
c = merge(a, b);
array_print(c);
array_destroy(a);
array_destroy(b);
array_destroy(c);
return 0;
}
If you've read so far, here's the lowdown:
Organzie your code. That applies to code layout as much as writing small, generally applicable functions instead of doing everything "by hand". (The array type above is a bit on the fence: It uses functions, but getting at the data is still done via accessing the struct fields. You could even change the szie and length, whixh shouldn't really happen.)
Enable compiler warnings with -Wall. You will get useful information about potential (and often actual) errors.
Good luck!
I'm trying to create a function that creates a variable sized 2D funct array. I'm using the following code, which seems to work just fine on its own:
typedef struct
{
//Starter Properties
int TypeB;
int TypeF;
int TypeW;
//Randomized Properties
int RandB;
int RandF;
int RandW;
//Derived Properties
int Speed;
} MapTileData;
MapTileData **Map;
int i, x=5, y=5;
//Allocate Initial Space
Map = (MapTileData**)calloc(x, sizeof(MapTileData));
for(i = 0; i < x; i++)
{
Map[i] = (MapTileData*)calloc(y, sizeof(MapTileData));
}
So the above code creates a 2D struct array. My attempts to move the code to a function have been less successful, giving segmentation faults when trying to print the array:
void CreateMap(MapTileData **Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
Map = (MapTileData**)calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = (MapTileData*)calloc(ySize, sizeof(MapTileData));
}
}
Used in the code:
MapTileData **MapTile;
CreateMap(MapTile,5,5);
Any and all help is greatly appreciated!
Function arguments are passed by value in C and modifying arguments in callee won't affect caller's local variables.
Use pointers to modify caller's local variables.
void CreateMap(MapTileData ***Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
*Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
(*Map)[i] = calloc(ySize, sizeof(MapTileData));
}
}
Usage in the code:
MapTileData **MapTile;
CreateMap(&MapTile,5,5);
Alternate way: Pass the allocated array via the return value.
MapTileData **CreateMap(int xSize, int ySize)
{
//Variables
MapTileData **Map;
int i;
//Allocate Initial Space
Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = calloc(ySize, sizeof(MapTileData));
}
//Return the value
return Map;
}
Usage in the code:
MapTileData **MapTile;
Maptile = CreateMap(5,5);
Also note that they say you shouldn't cast the result of malloc() and its family in C.
The code works if i use the name of the struct array directly for the allocation, but not from the function argument. Otherwise it returns memory error.
typedef struct COORD
{
int xp;
int yp;
} coord;
coord** xy;
void allocate(coord** COORD)
{
int i;
//allocate COORD[500][460]
COORD = (coord**)malloc(sizeof(coord*)*500);
for(i=0; i<500; i++)
{
COORD[i] = (coord*)malloc(sizeof(coord)*460);
}
// freeing
for (i=0; i<500; i++) free(COORD[i]);
free(COORD);
}
//function call: allocate(xy);
//That is the code that leeds to the error
Using just xy instead of COORD works. And i am all wondering why is that not working.
You are mixing up various coding styles here. It's not clear what exactly you want to achieve. Pick one according to your task.
Temporary buffer
You need a large temporary buffer that should be allocated on the heap and that does not need to be seen from outside. Just create a local variable:
void do_stuff(int w, int h)
{
coord **p;
int i;
p = malloc(h * sizeof(*p));
for (i = 0; i < h; i++) p[i] = malloc(w * sizeof(**p));;
// do stuff
for (i = 0; i < h; i++) free(p[i]);
free(p);
}
Allocate memory for further use
You want to allocate storage that your client code can use. Then provide two functions, one that allocates and one that frees the memory:
coord **create(int w, int h)
{
coord **p;
int i;
p = malloc(h * sizeof(*p));
for (i = 0; i < h; i++) p[i] = malloc(w * sizeof(**p));
return p;
}
void destroy(coord **p, int h)
{
int i;
for (i = 0; i < h; i++) free(p[i]);
free(p);
}
Your client code can then use the memory between these calls:
coord **p = create(500, 460);
// do stuff
drestroy(p, 500);
(Note that you have to pass the height to destroy, which is a bit unfortunate. It might be cleaner to create a wrapper struct that hold information about width and height and the pointer.)
Allocate memory for a global variable
You have a single instance of a global pointer. Then your functions always operate on that pointer and you don't need any further information on it (except the dimensions):
coord **global = NULL;
void destroy_global(int h)
{
int i;
for (i = 0; i < h; i++) free(global[i]);
free(global);
global = NULL;
}
void create_global(int w, int h)
{
int i;
if (global != NULL) free_global();
global = alloc(h * sizeof(*global));
for (i = 0; i < h; i++) global[i] = malloc(w * sizeof(**global));
}
Note that you should include <stdlib.h> for all memory functions and the NULL macro.
Addendum According to your comment, you want to allocate memory for a bitmap. That's option 2 above.
I recommend to create an object structure. You can pass a pointerv to that structure as handle to a bunch of functions. You can create the object with a function that returns that handle.
The following sketches a rough design for a bitmap object.
typedef struct Pixel Pixel;
typedef struct Bitmap Bitmap;
struct Pixel {
uint8_t r, g, b;
};
struct Bitmap {
int height;
int width;
Pixel **pixel;
};
Bitmap *bitmap_new(int w, int h)
{
Bitmap *bmp = malloc(sizeof(*bmp));
int i;
bmp->height = h;
bmp->width = w;
bmp->pixel = malloc(h * sizeof(*bmp->pixel));
for (i = 0; i < h; i++) {
bmp->pixel[i] = malloc(w * sizeof(**bmp->pixel));
}
return p;
}
void bitmap_delete(Bitmap *bmp)
{
int i;
for (i = 0; i < h; i++) free(bmp->pixel[i]);
free(bmp->pixel);
free(bmp);
}
Bitmap *bitmap_read(const char *fn)
{
Bitmap *bmp;
FILE *f = fopen(fn, "rb");
// read and allocate
return bmp;
}
void bitmap_blank(Bitmap *bmp, int r, int g, int b)
{
for (i = 0; i < bitmap->height; i++) {
for (j = 0; j < bitmap->width; j++) {
bmp->pixel[i][j].r = r;
bmp->pixel[i][j].g = g;
bmp->pixel[i][j].b = b;
}
}
}
void bitmap_mirror_x(Bitmap *bmp)
{
// do stuff
}
int bitmap_write(Bitmap *bmp, const char *fn)
{
FILE *f = fopen(fn, "rb");
// write bitmap to file
return 0;
}
The design is similar to the interface to FILE *: fopen gives you a handle (or NULL; error checking is omitted in the code above) and fread, fprintf, fseek and family take a pointer to the file as argument. Finally call fclose to close the file on disk and to free any ressources fopen has claimed.
Have you tried to compile this code? There are a number of errors.
First, the type of main should always be 'int main(int argc, char *argv[])'
Second, you need to '#include <stdlib.h>' at the top of your file to get the return type of malloc/free and friends.
Third, you are not declaring 'i'.
Fourth, you are using the same name 'COORD' as both a struct name and as a variable. Don't do this, it will cause you problems.
Sending incorrect code makes it very difficult to figure out what the root of your problem is, but I suspect it's the overloading of 'COORD'.
typedef struct COORD
{
int xp;
int yp;
} coord;
coord** xy;
void allocate(coord** COORD)
{
int i;
//allocate COORD[500][460]
COORD = (coord**)malloc(sizeof(coord*)*500);
for(i=0; i<500; i++)
{
COORD[i] = (coord*)malloc(sizeof(coord)*460);
}
// freeing
for (i=0; i<500; i++) free(COORD[i]);
free(COORD);
}
//function call: allocate();
//That is the code that works
The problem is that the function allocate() cannot change the value of xy outside itself. This is because C is call by value, the called function only gets the values of its arguments, not any kind of references to the expressions in the caller's context.
It needs to be:
void allocate(coord ***c)
{
}
and:
coord **xy;
allocate(&xy);
which of course is silly: the proper design would be for allocate() to return the new address:
coord ** allocate(void)
{
}
with use like:
coord **xy = allocate();
Probably it would be even better to have the dimensions as parameters to the function, since magic numbers are generally not a good thing:
coord ** allocate(size_t width, size_t height);
typedef struct
{
int xp;
int yp;
} Coord;
Coord **xy;
Coord** allocate(size_t height, size_t width)
{
int i;
Coord **arr;
arr = malloc(sizeof(Coord*)*height);
for(i=0; i<height; i++) {
arr[i] = malloc(sizeof(coord)*width);
}
return arr;
}
void allocate2(Coord ***p_arr, size_t height, size_t width)
{
int i;
Coord **arr;
arr = *p_arr;
arr = malloc(sizeof(Coord*)*height);
for(i=0; i<height; i++) {
arr[i] = malloc(sizeof(coord)*width);
}
}
void deallocate(Coord **arr, size_t height)
{
for (i=0; i<500; i++) {
free(arr[i]);
}
free(arr);
}
int main()
{
Coord **arr_2;
Coord ***p_arr_3;
allocate2(&xy, 500, 460);
/* do something with global array, xy, e.g. */
xy[1][2].xp = 100;
xy[1][2].yp = 200;
deallocate(xy, 500);
arr_2 = allocate(500, 460);
/* do something with local array, arr_2 */
deallocate(arr_2, 500);
allocate2(p_arr_3, 500, 460);
/* do something with ptr to local array, p_arr_3 */
deallocate(*p_arr_3, 500);
return 0;
}
I am a newbie to C.
I am trying to return a 2d array from a function.
It is something like this
int *MakeGridOfCounts(int Grid[][6])
{
int cGrid[6][6] = {{0, }, {0, }, {0, }, {0, }, {0, }, {0, }};
int (*p)[6] = cGrid;
return (int*)p;
}
I know this causes an error, need help. thanks
The C language has a basic flaw: it is impossible to return arrays from functions.
There are many workarounds for this; i'll describe three.
Replace by a pointer to an array
Return a pointer instead of an array itself. This leads to another problem in C: when a function returns a pointer to something, it should usually allocate the something dynamically. You should not forget to deallocate this later (when the array is not needed anymore).
typedef int (*pointer_to_array)[6][6];
pointer_to_array workaround1()
{
pointer_to_array result = malloc(sizeof(*result));
(*result)[0][0] = 0;
(*result)[1][0] = 0;
(*result)[2][0] = 0;
(*result)[3][0] = 0;
(*result)[4][0] = 0;
(*result)[5][0] = 0;
return result;
}
Replace by a pointer to int
A 2-D array appears just as a sequence of numbers in memory, so you can replace it by a pointer to first element. You clearly stated that you want to return an array, but your example code returns a pointer to int, so maybe you can change the rest of your code accordingly.
int *workaround2()
{
int temp[6][6] = {{0}}; // initializes a temporary array to zeros
int *result = malloc(sizeof(int) * 6 * 6); // allocates a one-dimensional array
memcpy(result, temp, sizeof(int) * 6 * 6); // copies stuff
return result; // cannot return an array but can return a pointer!
}
Wrap with a structure
It sounds silly, but functions can return structures even though they cannot return arrays! Even if the returned structure contains an array.
struct array_inside
{
int array[6][6];
};
struct array_inside workaround3()
{
struct array_inside result = {{{0}}};
return result;
}
It sounds like you want a function returning pointer to array[6] of int:
int (*makeGrid())[6]
{
return calloc(6*6,sizeof(int)); //zeros the memory as in your example.
}
You would call and use it like so:
int (*arr)[6] = makeGrid();
arr[4][3] = 3; //etc...
Try this out, compiles fine with GCC on my mac..
typedef struct _intGrid_t{
int **data;
int width;
int height;
} *IntGrid;
IntGrid makeGridWithSize(int width, int height);
IntGrid makeGridWithSize(int width, int height)
{
IntGrid grid = malloc(sizeof(struct _intGrid_t));
int **data = (int **) malloc(sizeof(int *) * width);
for (int i = 0; i < width; i++) {
data[i] = malloc(sizeof(int) * height);
memset(data[i], 0, sizeof(int) * height);
}
grid->data = data;
grid->width = width;
grid->height = height;
return grid;
}
void printGrid(IntGrid grid);
void printGrid(IntGrid grid)
{
printf(" { \n");
for (int i =0; i < grid->width; i++) {
printf(" { ");
for (int j = 0; j < grid->height; j++) {
printf("%i", grid->data[i][j]);
if (j != grid->height - 1)
{
printf(", ");
}
}
printf(" } \n");
}
printf(" } \n");
}
void freeGrid(IntGrid grid);
void freeGrid(IntGrid grid)
{
for (int i = 0; i < grid->width; i++) {
free(grid->data[i]);
}
free(grid->data);
free(grid);
}
int main (int argc, const char * argv[])
{
srand((int) time(NULL));
IntGrid grid = makeGridWithSize(10, 10);
for (int i = 0; i < grid->width; i++) {
for (int j = 0; j < grid->height; j++) {
grid->data[i][j] = rand() % 10;
}
}
printGrid(grid);
freeGrid(grid);
return 0;
}