Проверка памяти Valgrind при дублировании строк - PullRequest
0 голосов
/ 19 апреля 2020

Я пишу программу, которая реализует карту \ словарь (те из вас, кто знаком с 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;
}
}
...