首页 > 解决方案 > 复制字符串时的 Valgrind 内存检查

问题描述

我正在编写一个实现 map\dictionary 的程序(熟悉 python 的人应该知道它)。一切都编译了,我的测试工作正常。我唯一的问题是当我使用 valgrind 内存检查运行程序时。

valgrind 引导我进入的函数是将元素插入字典的函数(所有元素都由具有 2 个字段的结构表示:char* 键、char* 值)。

编码:

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;
}

复制字符串函数:

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)

如果有人发现泄漏,我会很高兴听到

编辑

地图的销毁功能:

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;
}
}

标签: cstringmemory-leaksvalgrindheap-memory

解决方案


推荐阅读