i thought my mallocs were correct
They are not. We need a picture. You have two separate malloc blocks, one of size 6 (assuming sizeof(uint8_t)
is 1); let's call it B1, and one of size 2 (call it B2). You also have two pointers: a
that points to the first block, and *a
that points to the second block.
a --> [*a, x, y]
|
|-> [w, z]
Let's assume you are on a 32-bit system, and sizeof(void*)
is 4.
Line *a = malloc...
initializes the first 4 bytes of B1 to point to B2, leaving the last 2 bytes of B1 (the x
, y
bytes) uninitialized.
Line a[0][0] = ...
initializes the first byte of B2 (the w
byte) to 1.
Line a[1][0] = ...
uses 4 bytes at offset 4 in block B1 as a pointer.
The trouble is: the first two of these bytes (x
, y
bytes) are uninitialized, and the second two bytes are outsize of the allocated block altogether. So you have two bugs for the price of one.
You can clearly see that in e.g. valgrind output:
==9576== Invalid read of size 4
==9576== at 0x804845A: main (/tmp/t.c:12)
==9576== Address 0x420005c is 4 bytes inside a block of size 6 alloc'd
==9576== at 0x402DBFA: malloc (valgrind/coregrind/m_replacemalloc/vg_replace_malloc.c:270)
==9576== by 0x8048431: main (/tmp/t.c:8)
==9576==
==9576== Use of uninitialised value of size 4
==9576== at 0x804845C: main (/tmp/t.c:12)
==9576==
==9576== Invalid write of size 1
==9576== at 0x804845C: main (/tmp/t.c:12)
==9576== Address 0x0 is not stack'd, malloc'd or (recently) free'd
Now, it's not clear what the size of matrix you wanted to allocate is (where did the 6 come from?).
Assuming you wanted to create a dynamically allocated MxN
array, the correct code to do so would be:
uint8_t **a;
a = malloc(M * sizeof(a[0]));
for (j = 0; j < M; ++j)
a[j] = malloc(N * sizeof(a[0][0]));
// Now all M by N elements are accessible:
for (j = 0; j < M; ++j)
for (k = 0; k < N; ++k)
a[j][k] = 1;
// cleanup.
for (j = 0; j < M; ++j)
free(a[j]);
free(a);