Can';在终止并正确返回正确输出的程序上找不到valgrind错误
即使程序正确终止并提供正确的输出,并且没有内存泄漏,valgrind也给了我一些此类错误:Can';在终止并正确返回正确输出的程序上找不到valgrind错误,c,valgrind,C,Valgrind,即使程序正确终止并提供正确的输出,并且没有内存泄漏,valgrind也给了我一些此类错误: Invalid read of size 1 ==910== at 0x108DD4: fnv_hash_function (user.c:24) ==910== by 0x108E17: hash (user.c:29) ==910== by 0x109A50: icl_hash_find (icl_hash.c:114) ==910== by 0x1094DB: db_requ
Invalid read of size 1
==910== at 0x108DD4: fnv_hash_function (user.c:24)
==910== by 0x108E17: hash (user.c:29)
==910== by 0x109A50: icl_hash_find (icl_hash.c:114)
==910== by 0x1094DB: db_request (user.c:197)
==910== by 0x108D2E: main (tuser.c:65)
==910== Address 0x5416f50 is 0 bytes inside a block of size 15 free'd
==910== at 0x4C2E10B: free (vg_replace_malloc.c:530)
==910== by 0x109152: freeKey (user.c:138)
==910== by 0x109CF2: icl_hash_delete (icl_hash.c:192)
==910== by 0x109796: db_request (user.c:222)
==910== by 0x108CF8: main (tuser.c:59)
==910== Block was alloc'd at
==910== at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==910== by 0x108BDC: main (tuser.c:35)
hash
和fnv\u hash\u函数
就是这样定义的
static inline unsigned int fnv_hash_function( void *key, int len ) {
unsigned char *p = (unsigned char*)key;
unsigned int h = 2166136261u;
int i;
for ( i = 0; i < len; i++ )
h = ( h * 16777619 ) ^ p[i]; //this is the line 24
return h;
}
unsigned int hash(void *key){
return fnv_hash_function(key, strlen(key));
}
void *
icl_hash_find(icl_hash_t *ht, void* key)
{
icl_entry_t* curr;
unsigned int hash_val;
if(!ht || !key) return NULL;
hash_val = (* ht->hash_function)(key) % ht->nbuckets;
for (curr=ht->buckets[hash_val]; curr != NULL; curr=curr->next)
if ( ht->hash_key_compare(curr->key, key))
return(curr->data);
return NULL;
}
我在该库的测试套件上尝试了valgrind,但没有发现任何错误,因此我怀疑问题是否存在
编辑:
在该for循环中分配密钥:
char * s; //string used as key
for(int i = 0; i < N; i++){
s = (char *)malloc(NAMELEN * sizeof(char));
sprintf(s, "Utente %d", i);
u = create_user( s , i);
if(!db_request(db, s, u, PUT)){
perror("problema PUT");
exit(EXIT_FAILURE);
}
.
.
.
但我找不到问题,我开始认为问题出在icl_哈希库中
当我在测试函数中刚刚删除的元素上调用GET时,就会出现问题
if(!db_request(db, s , u ,DELETE)){
perror("problema DELETE");
exit(EXIT_FAILURE);
};
//provo a ottenerlo di nuovo
//The error happens here
if(!db_request(db, s , u ,GET)){
perror("GET");
exit(EXIT_FAILURE);
};
get唯一要做的就是调用此函数:
void *
icl_hash_find(icl_hash_t *ht, void* key)
{
icl_entry_t* curr;
unsigned int hash_val;
if(!ht || !key) return NULL;
hash_val = (* ht->hash_function)(key) % ht->nbuckets;
for (curr=ht->buckets[hash_val]; curr != NULL; curr=curr->next)
if ( ht->hash_key_compare(curr->key, key))
return(curr->data);
return NULL;
}
Valgrind告诉您,
fnv_hash_函数
函数有问题。在该函数中,您可以在freeKey
中释放(释放)内存后访问内存。它甚至告诉你,你访问它的时候正好在内存块的开头。您在main(tuser.c:35)
中分配了该内存。你的程序是偶然运行的。只要所讨论的内存块不会在内存页的开头结束,并且它将是该页上释放的最后一个块,那么该页将(可能-取决于分配器策略)从进程空间中取消映射,它将继续工作。在取消映射之后,如果您访问它(如在fnv\u hash\u函数中
),您的程序将在您尝试访问它的那一刻崩溃
该块何时可以作为页面上的第一个块结束并成为最后一个被释放的块?-很难说在您对源代码或底层库(包括您无法控制的系统库)进行任何更改后,可能会发生这种情况。您对已释放内存的无效访问: 在文件
user.c
中的函数db\u request()
的第222行调用icl\u hash\u delete()
时释放了该块。调用user.c
中db\u request()
中第197行的icl\u hash\u find()
时进行了无效访问。您说,icl\u散列*
代码已提供给您
如果没有函数体db_request()
,就很难确定发生了什么,但至少有两种可能性
icl\u hash*
函数中的代码错误处理数据icl\u hash.c
函数的提供程序相当可靠,那么可以合理地假设问题出在db\u request()
中的代码中。仔细看第197行和第222行,以及传递给icl\u hash\u find()
和icl\u hash\u delete()函数的变量(指针)。再次查看手册页面中的这些函数,了解规则是什么
如果您不确定icl_hash.c
中的代码质量,您应该自己创建一个较小的MCVE,创建一个哈希表,添加一些行,查找一些行,删除一些条目,并执行更多的查找。这将帮助您确定代码或icl_hash.c
代码中是否存在问题
由于内存是在main()
中分配的,而不是在db\u request()
中分配的,因此您可能需要查看在该级别上正在执行的操作,但我的猜测是,您将该指针传递到db\u request()
并在添加条目时将其所有权交给哈希表,icl\u hash\u delete()的规范
表示它将释放您交给哈希表的内存,但您仍然意外地持有指向现在已释放内存的指针(指向db\u request()函数的参数)。您必须非常小心,以确保知道谁拥有什么内存以及该内存何时被释放。似乎键
包含的字符串比它指向的内存长,并且您的函数正在使用无效索引i访问p[i]
。您的代码片段没有显示密钥分配和填充的位置,这可能是罪魁祸首。密钥真的是以0结尾的吗?(也就是说,strlen对它有意义吗?)看起来像是icl\u hash\u find()
传递了一个密钥,这个密钥以前已经是免费的。valgrind消息非常具体,请发布一个。虽然你的问题格式良好,表现出很好的表达能力,但你确实需要一个MCVE,这样这里的人可以通过编译你的MCVE和使用调试工具来帮助你发现问题。不要期望人们为您编写代码。发布一些完整的内容,并以可复制的方式说明问题。@melpomene-是的,你是对的,我更正了答案。他还释放了freeKey(user.c:138)
的内存,我解决了问题。错误在于icl_哈希_删除。该函数在释放元素时也释放了键
void *
icl_hash_find(icl_hash_t *ht, void* key)
{
icl_entry_t* curr;
unsigned int hash_val;
if(!ht || !key) return NULL;
hash_val = (* ht->hash_function)(key) % ht->nbuckets;
for (curr=ht->buckets[hash_val]; curr != NULL; curr=curr->next)
if ( ht->hash_key_compare(curr->key, key))
return(curr->data);
return NULL;
}
Invalid read of size 1
==910== at 0x108DD4: fnv_hash_function (user.c:24)
==910== by 0x108E17: hash (user.c:29)
==910== by 0x109A50: icl_hash_find (icl_hash.c:114)
==910== by 0x1094DB: db_request (user.c:197)
==910== by 0x108D2E: main (tuser.c:65)
==910== Address 0x5416f50 is 0 bytes inside a block of size 15 free'd
==910== at 0x4C2E10B: free (vg_replace_malloc.c:530)
==910== by 0x109152: freeKey (user.c:138)
==910== by 0x109CF2: icl_hash_delete (icl_hash.c:192)
==910== by 0x109796: db_request (user.c:222)
==910== by 0x108CF8: main (tuser.c:59)
==910== Block was alloc'd at
==910== at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==910== by 0x108BDC: main (tuser.c:35)