Search code examples
cdynamic-memory-allocationtypedefcompound-literals

Initializing a dynamically allocated array with a compound literal


I am allocating memory for my float3x3 matrix as such:

typedef float float3x3[3][3];
float3x3 *g = malloc(sizeof g);
g = &(float3x3){
    { 1, 0, 0 },
    { 0, 1, 0 },
    { 0, 0, 1 }
};
printfloat3x3(*g);

The above compiles, however I am allocating space for *g then setting g's pointer to a static 3x3 matrix. Not exactly what I want to do if I want to free g.

How can I initialize g using a compound literal after allocation? I tried this but it wont compile:

typedef float float3x3[3][3];
float3x3 *g = malloc(sizeof g);
g = (float3x3){
    { 1, 0, 0 },
    { 0, 1, 0 },
    { 0, 0, 1 }
};
printfloat3x3(*g);
free(g);
cc -fsanitize=address -Wall -Wextra -pedantic -O2 -o test-gmath test-gmath.c gmath.c -lm
test-gmath.c: In function ‘GMATH_Tests’:
test-gmath.c:69:11: warning: assignment to ‘float (*)[3][3]’ from incompatible pointer type ‘float (*)[3]’ [-Wincompa
tible-pointer-types]
   69 |         g = (float3x3){
      |           ^
test-gmath.c:75:9: warning: ‘free’ called on unallocated object ‘({anonymous})’ [-Wfree-nonheap-object]
   75 |         free(g);
      |         ^~~~~~~
test-gmath.c:69:23: note: declared here
   69 |         g = (float3x3){
      |                       ^

(3 of 11): warning: assignment to ‘float (*)[3][3]’ from incompatible pointer type ‘float (*)[3]’ [-Wincompatible-poi
nter-types]

Solution

  • First, you need to allocate the size of the structure, not the pointer:

    float3x3 *g = malloc(sizeof *g);
    

    Then to initialize the contents, you can use memcpy()

    memcpy(g, &(float3x3){
        { 1, 0, 0 },
        { 0, 1, 0 },
        { 0, 0, 1 }
    }, sizeof *g);
    

    Your code causes a memory leak because you're reassigning the pointer to point to the memory of the compound literal. That's also why free() fails, because it no longer points to the memory returned by malloc().