To learn more of C, I'm trying to recreate basic data structures. Here's a minimal example of my attempt at an array, which compiles and runs but has a problem detected by valgrind:
#include <stdlib.h>
#include <stdio.h>
typedef void * vp_t;
typedef struct {
int len;
vp_t *start;
} arr_t;
arr_t * array_new(int len) {
arr_t *arr = malloc(sizeof(arr_t));
arr->start = malloc(len * sizeof(vp_t));
arr->len = len;
return arr;
}
void array_set(arr_t *arr, int i, vp_t vp) {
vp_t *dest = arr->start + i * sizeof(vp_t);
*dest = vp;
}
int array_get(arr_t *arr, int i) {
int *p = *(arr->start + i * sizeof(vp_t));
return *p;
}
void array_delete(arr_t *arr) {
free(arr->start);
free(arr);
}
int main() {
int x=0, y=1, z=2;
arr_t *arr = array_new(3);
array_set(arr, 0, &x);
array_set(arr, 1, &y);
array_set(arr, 2, &z);
for (int i = 0; i < 3; ++i) printf("%i ", array_get(arr, i));
putchar('\n');
array_delete(arr);
return 0;
}
The program outputs 1 2 3 as expected. However, valgrind is detecting a problem the second and third time I call the array_set function. Running valgrind against the example code here, I get:
==91933== Invalid write of size 8
==91933== at 0x109244: array_set (min.c:22)
==91933== by 0x109312: main (min.c:39)
==91933== Address 0x4a990d0 is 32 bytes before an unallocated block of size 4,194,032 in arena "client"
==91933==
==91933==
==91933== Process terminating with default action of signal 11 (SIGSEGV)
==91933== Access not within mapped region at address 0x2003A98F4C
==91933== at 0x109244: array_set (min.c:22)
==91933== by 0x109327: main (min.c:40)
min.c:22 refers to *dest = vp in the array_set function. min.c:39 refers to array_set(arr, 1, &y). Valgrind does not complain about line 38, array_set(arr, 0, &x).
I've been poking around with gdb, but I've not figured it out yet. Thanks for taking a look.
set()andget(), don't multiply by the size of the object. Eg:vp_t *dest = arr->start+i;You deal with objects. The compiler knows how many bytes each object occupies.printf("%p\n", arr->start + i * sizeof(vp_t));Is that what you expect? Then print it likeprintf("%p\n", arr->start + i );Is that what you expect?vp_tpointers withint's... What are you trying to achieve? The compiler should be giving you all sorts of warnings and errors...