I have these structs with which I would like to implement a map
typedef struct {
const char *name;
int number;
} Entry;
typedef struct {
int available;
int guard;
Entry *entries;
} Map;
and code to work to initialise and put elements in it:
Map *map_init() {
Map *res = (Map *) malloc(sizeof(Map));
res->available = 4;
res->guard = 0;
res->entries = (Entry *) malloc(4 * sizeof(Entry));
return res;
}
int map_put(Map *map, const char *name, int nr) {
Entry entry;
int i = 0;
for (i = 0; i < map->guard; ++i) {
entry = map->entries[i];
printf("entry ( x , %u) at %p (%p)\n", entry.number, &entry, entry.name);
if (!strcmp(entry.name, name)) // Segmentation fault here
return 0;
}
entry = map->entries[map->guard++];
entry.name = name;
entry.number = nr;
printf("entry (%s, %u) at %p (%p)\n", entry.name, entry.number, &entry, entry.name);
return 1;
}
when I run my main method
int main(int argc, char **argv) {
printf("Initialising...\n");
Map *map = map_init();
printf("Putting...\n");
map_put(map, "test", 2);
map_put(map, "some", 1);
// ...
free(map->entries);
free(map);
return 0;
}
I get as output
Initialising...
Putting...
entry (test, 2) at 0x7fff50b32a90 (0x10f0cdf77)
entry ( x , 0) at 0x7fff50b32a90 (0x5000000000000000)
Segmentation fault: 11
from which I could derive that the segmentation fault is due to the fact that entry.name
does not point to a string anymore (also the number is lost, but this does not lead to unauthorised memory access). After I set the data in the first invocation of map_put
, everything seems to be stored in the correct places.
Anyone an idea where these entries could be overwritten or why the values are not stored?
The problem is this:
entry = map->entries[map->guard++];
Here you copy the data from the array into the entry
structure instance. Then you modify the data of entry
and discard those modifications. The (original) structure data in the array is still unmodified.
That will of course lead to undefined behavior when you in the next call to map_put
use the uninitialized structures in the array.
Either modify the array structure instance directly and increase map->guard
separately. Or make entry
a pointer and make it point to the array element.