Я пишу программу, которая реализует карту \ словарь (те из вас, кто знаком с python, должны это знать). Все компилируется и мои тесты работают правильно. Единственная проблема, с которой я сталкиваюсь, это когда я запускаю программу с проверкой памяти в valgrind.
Функция, в которую ведет меня valgrind, - это та, которая вставляет элемент в словарь (все элементы представлены структурой, имеющей 2 поля). : char * key, char * value).
Код:
MapResult mapPut(Map map, const char* key, const char* data){
if( map == NULL || key == NULL || data == NULL){
return MAP_NULL_ARGUMENT;
}
//check if key exists in map
if(mapContains(map, key)){//checks if the key already exists in the map
if(strcmp(map->dictionary[elementIndex(map,key)].value, data) == 0){
return MAP_SUCCESS;
}
else{
char* new_value = copyString(data);
if(new_value == NULL){
return MAP_OUT_OF_MEMORY;
}
map->dictionary[elementIndex(map,key)].value = new_value;
return MAP_SUCCESS;
}
}
// expands the array if necessary
if(map->size == map->max_size){
if(expand(map) == MAP_OUT_OF_MEMORY){
return MAP_OUT_OF_MEMORY;
}
}
char* new_key = copyString(key);
char* new_value = copyString(data); //This is line 194
if(new_value == NULL || new_key == NULL){
return MAP_OUT_OF_MEMORY;
}
map->dictionary[map->size].key = new_key;
map->dictionary[map->size++].value = new_value;
return MAP_SUCCESS;
}
Функция copyString:
static char* copyString(const char* str){
char* new_str = malloc(strlen(str) + 1); //this is line 49
if(new_str == NULL){
return NULL;
}
return strcpy(new_str, str);//returning the new string after it has been assigend with new value
}
Структура реализация:
typedef struct element{
char* key;
char* value;
}*Element;
Очевидно, утечка происходит из copyString, мне не удалось найти, что это такое, но я предполагаю, что это как-то связано с процессом дублирования строки.
Вывод Valgrind ( все остальные блоки одинаковы, все категоризировано как определенно потерянные байты):
==4694== 7 bytes in 1 blocks are definitely lost in loss record 3 of 5
==4694== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4694== by 0x108AB2: copyString (map.c:49)
==4694== by 0x108FF3: mapPut (map.c:194)
==4694== by 0x109A46: testMapPutGet (test_file.c:71)
==4694== by 0x10B146: main (test_file.c:296)
если кто-нибудь обнаружит утечку, я буду рад услышать
edit
Функция уничтожения для карты:
void mapDestroy(Map map){
if(map == NULL){
return;
}
while(mapGetSize(map) > 0){
mapRemove(map, mapGetFirst(map));//map getFirst returns first key in the map\array
}
// TODO: Free key and value
free(map->dictionary);
free(map);
}
MapResult mapRemove(Map map, const char* key){
assert(map != NULL);
if(key == NULL){
return MAP_NULL_ARGUMENT;
}
int index = elementIndex(map, key);
if(index == NOT_FOUND){
return MAP_ITEM_DOES_NOT_EXIST;
}
return removeElement(map, index);
}
static MapResult removeElement(Map map, int index){
assert(map != NULL && map->size > 0);
free(map->dictionary[index].key);
free(map->dictionary[index].value);
for(int i = index; i < map->size - 1 ; i++){
map->dictionary[i] = map->dictionary[i + 1];
}
if(map->size > 1){
Element tmp = realloc(map->dictionary, (map->max_size - 1) * sizeof(*tmp));
if(tmp == NULL){
return MAP_OUT_OF_MEMORY;
}
map->max_size--;
map->size--;
map->dictionary = tmp;
return MAP_SUCCESS;
}
else{
map->size--;
return MAP_SUCCESS;
}
}