c - 复制字符串时的 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;
}
}
解决方案
推荐阅读
- azure-keyvault - 将机密传递给 Azure 数据工厂中的 Web 活动
- sql - 插入后获取主键值不知道主键的列名
- react-native - 通过 UIManager['getConstants'] 直接从 UIManager 访问视图管理器配置
- java - 如何找到 git 子模块的分支名称?
- sql - Hive 爆炸并从字符串中提取值
- machine-learning - 图像处理,可以使用什么技术来确定位图中的最短路径
- bash - 从文本文件中获取最新日期
- java - 获取导致源代码语法错误的parserRuleContexts
- python - 如何使用 torch.multiprocessing.Pool (Python) 摆脱僵尸进程
- python - 将字符串列(2018 年 1 月)转换为 pyspark 数据帧的日期列(01-01-2018)