Here's the problem, I'm trying to allocate a struct containing an array of pixels but it gives me a segfault and I can't find the error, here's how I originally tried to do it:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
int len;
uint16_t tex_w;
uint16_t tex_h;
uint32_t** tex;
} Tex_Array;
int main(void)
{
const uint8_t tex_num = 8;
const uint16_t tex_w = 64;
const uint16_t tex_h = 64;
Tex_Array* wall_tex = malloc(sizeof(Tex_Array) (tex_w * tex_h) * tex_num * sizeof(uint32_t));
/* Texture generation */
for(int x = 0; x < tex_w; x ) {
for(int y = 0; y < tex_h; y )
{
int xorcolor = (x * 256 / tex_w) ^ (y * 256 / tex_h);
int ycolor = y * 256 / tex_h;
int xycolor = y * 128 / tex_h x * 128 / tex_w;
wall_tex->tex[0][tex_w * y x] = 65536 * 254 * (x != y && x != tex_w - y);
wall_tex->tex[1][tex_w * y x] = xycolor 256 * xycolor 65536 * xycolor;
wall_tex->tex[2][tex_w * y x] = 256 * xycolor 65536 * xycolor;
wall_tex->tex[3][tex_w * y x] = xorcolor 256 * xorcolor 65536 * xorcolor;
wall_tex->tex[4][tex_w * y x] = 256 * xorcolor;
wall_tex->tex[5][tex_w * y x] = 65536 * 192 * (x % 16 && y % 16);
wall_tex->tex[6][tex_w * y x] = 65536 * ycolor;
wall_tex->tex[7][tex_w * y x] = 128 256 * 128 65536 * 128;
}
}
/* Test if the program arrives here */
printf("Generation is finished !\n");
/* rest of initialization just for example */
wall_tex->len = tex_num;
wall_tex->tex_w = tex_w;
wall_tex->tex_h = tex_h;
return 0;
}
What I understand even less is that I tried to do it even more "literally" as below, with memcpy()
, but it gives me exactly the same result (segfault) at copy time :
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct {
int len;
uint16_t tex_w;
uint16_t tex_h;
uint32_t** tex;
} Tex_Array;
int main(void)
{
const uint8_t tex_num = 8;
const uint16_t tex_w = 64;
const uint16_t tex_h = 64;
uint32_t tex[8][tex_w * tex_h];
/* Texture generation */
for(int x = 0; x < tex_w; x ) {
for(int y = 0; y < tex_h; y )
{
int xorcolor = (x * 256 / tex_w) ^ (y * 256 / tex_h);
int ycolor = y * 256 / tex_h;
int xycolor = y * 128 / tex_h x * 128 / tex_w;
tex[0][tex_w * y x] = 65536 * 254 * (x != y && x != tex_w - y);
tex[1][tex_w * y x] = xycolor 256 * xycolor 65536 * xycolor;
tex[2][tex_w * y x] = 256 * xycolor 65536 * xycolor;
tex[3][tex_w * y x] = xorcolor 256 * xorcolor 65536 * xorcolor;
tex[4][tex_w * y x] = 256 * xorcolor;
tex[5][tex_w * y x] = 65536 * 192 * (x % 16 && y % 16);
tex[6][tex_w * y x] = 65536 * ycolor;
tex[7][tex_w * y x] = 128 256 * 128 65536 * 128;
}
}
printf("Generation is finished !\n"); // It's okay'
/* rest of initialization */
Tex_Array* wall_tex = malloc(sizeof(Tex_Array) sizeof(tex));
wall_tex->len = tex_num;
wall_tex->tex_w = tex_w;
wall_tex->tex_h = tex_h;
memcpy(wall_tex->tex, tex, sizeof(tex)); // Segfault here
/* Test if the program arrives here */
printf("Struct alloc is finished !\n");
return 0;
}
Where am I going wrong with using malloc()
?
I want to clarify that these are just shortened examples and I need to be able to allocate this structure in the real project.
CodePudding user response:
You allocate too much space for your Tex_Array
structure, you end with a double-pointer, not an actual array embedded in the struct itself.
Really, what you should have is something like:
Tex_Array *wall_tex = malloc(sizeof(Tex_Array));
wall_tex->tex = malloc(tex_num * sizeof(uint32_t *));
for (size_t i = 0; i < tex_num; i)
wall_tex->tex[i] = malloc((tex_w * tex_h) * sizeof(uint32_t));
assuming that is what you want to do here.
This allocates a lot, however. We can still do it one large allocation and partition it up accordingly afterwards.
Tex_Array *wall_tex;
// Note that we use (char *) here since sizeof(char) == 1.
char *arena = malloc(sizeof(Tex_Array) (tex_w * tex_h) * tex_num * sizeof(uint32_t));
wall_tex = arena;
arena = sizeof(Tex_Array);
wall_tex->tex = arena;
arena = tex_num * sizeof(uint32_t *);
for (size_t i = 0; i < tex_num; i) {
wall_tex->tex[i] = arena;
arena = (tex_w * tex_h) * sizeof(uint32_t);
}
Hopefully understanding this can point you in the right direction.
CodePudding user response:
Like I said in my comment, your allocation is only for the wall_tex
pointer. Which you don't really need to be a pointer or do to dynamic allocation:
Tex_Array wall_tex; // Create one single Tex_Array structure object
Then you need to allocate the actual array for tex
itself:
wall_tex.tex = malloc(sizeof *wall_tex.tex * tex_num);
And lastly create the sub-arrays:
for (unsigned i = 0; i < tex_num; i)
{
wall_tex.tex[i] = malloc(sizeof *wall_tex.tex[0] * tex_w * tex_h);
}
If you need to dynamically allocate the Tex_Array
structure object itself, then allocate only it:
Tex_Array *wall_tex = malloc(sizeof *wall_tex);