What I'm trying to do here (for educational purposes) is to have a pointer to a pointer that behaves like an array but with a single memory allocation. Valgrind is complaining about this code and if I do a longer version of this with several allocations I start having segfaults while debugging in gdb.
It's allocating 144 bytes (24 bytes for the 3 pointers, then 3*40 bytes for the integers). l[0] is +24 bytes from l, l[1] +40 from l[0] and so on.
Can someone enlighten me about what I'm getting wrong?
gcc -o program -g -ansi -Wpedantic -Wall -Wextra main.c
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int **l;
int i, j, k;
int x = 3;
int y = 10;
size_t size_y = sizeof(int) * y;
size_t x_ptrs = x * sizeof(int*);
size_t mem_to_alloc = x_ptrs + x * size_y;
l = malloc(mem_to_alloc);
l[0] = (int*)l + x_ptrs;
l[1] = (int*)l + x_ptrs + size_y;
l[2] = (int*)l + x_ptrs + size_y * 2;
k = 0;
for(i = 0; i < x; i++)
for(j = 0; j < y; j++)
l[i][j] = (-k++)*12; /* just some number */
for(i = 0; i < x; i++) {
for(j = 0; j < y; j++) {
printf("%.3d\n", l[i][j]);
}
puts("");
}
free(l);
l = NULL;
return 0;
}
valgrind ./program
==1593== Memcheck, a memory error detector
==1593== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==1593== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==1593== Command: ./program
==1593==
==1593== Invalid write of size 4
==1593== at 0x4006E8: main (main.c:22)
==1593== Address 0x51d5140 is 48 bytes inside an unallocated block of size 4,194,000 in arena "client"
==1593==
000
-012
-024
-036
-048
-060
-072
-084
-096
-108
==1593== Invalid read of size 4
==1593== at 0x400738: main (main.c:26)
==1593== Address 0x51d5140 is 48 bytes inside an unallocated block of size 4,194,000 in arena "client"
==1593==
-120
-132
-144
-156
-168
-180
-192
-204
-216
-228
-240
-252
-264
-276
-288
-300
-312
-324
-336
-348
==1593==
==1593== HEAP SUMMARY:
==1593== in use at exit: 0 bytes in 0 blocks
==1593== total heap usage: 1 allocs, 1 frees, 144 bytes allocated
==1593==
==1593== All heap blocks were freed -- no leaks are possible
==1593==
==1593== For counts of detected and suppressed errors, rerun with: -v
==1593== ERROR SUMMARY: 40 errors from 2 contexts (suppressed: 0 from 0)