C语言 Valgrind:无效读取大小 4 -> sigsegv,在没有 valgrind 和 Visual Studio 的情况下工作正常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13546650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Valgrind: invalid read of size 4 -> sigsegv, works fine without valgrind and in visual studio
提问by HaS
I have implemented a compression algorithm (using huffman coding) which uses a priority queue of nodes (a struct i defined). Now, when i just run the code in linux or in visual studio, everything works fine. When I check for memory leaks in visual studio, none are given.
我已经实现了一个压缩算法(使用霍夫曼编码),它使用节点的优先级队列(我定义的结构)。现在,当我在 linux 或 Visual Studio 中运行代码时,一切正常。当我在 Visual Studio 中检查内存泄漏时,没有给出任何内容。
The problem now is, when I use valgrind to analyse my program, it terminates with signal 11 (sigsegv). The first error encountered is an 'invalid read of size 4' in the method delete min. Other errors after that are: Adress is 0 bytes inside a block of size 453 freed, invalid write of size 4, invalid free,delete or realloc.
现在的问题是,当我使用 valgrind 分析我的程序时,它以信号 11 (sigsegv) 终止。遇到的第一个错误是 delete min 方法中的“大小为 4 的无效读取”。之后的其他错误是:地址是大小为 453 的块内的 0 字节已释放、大小为 4 的无效写入、无效的释放、删除或重新分配。
Can anyone give me advice about what kind of error I possibly could have made? I've been searching the internet for hours, but cannot find what i'm doing wrong (especially since it just works when not using valgrind). Or tips how to debug and find out what's causing the read error.
任何人都可以就我可能犯的错误给我建议吗?我已经在互联网上搜索了几个小时,但找不到我做错了什么(特别是因为它在不使用 valgrind 时才有效)。或者提示如何调试并找出导致读取错误的原因。
Many Thanks!
非常感谢!
Here is the code in case somebody would want to review it, but I guess that's not that easy to just dive in this specific code.
这是代码,以防有人想要查看它,但我想仅仅深入了解这个特定代码并不容易。
I'm guessing it has something to do with the priority queue of the code:
我猜它与代码的优先级队列有关:
The part where I do the huffman part -> every time delete the 2 minimal nodes and add the sum of both back as one node.
我做霍夫曼部分的部分 - >每次删除2个最小节点并将两者的总和添加为一个节点。
while(queue->size > 1){
node* n1 = delete_min(queue);
node* n2 = delete_min(queue); // all the errors are encountered in this call
node* temp = (node*) calloc(sizeof(node),1);
temp->amount = n1->amount + n2->amount;
insert_node(queue,temp);
n1->parent = temp;
n2->parent = temp;
temp->left = n1;
temp->right = n2;
}
Here is are the delete_min and insert_node methods for the priority queue:
以下是优先级队列的 delete_min 和 insert_node 方法:
void insert_node(priority_queue* p_queue, node* x){
int i = p_queue->size;
if(i == 0){
p_queue->queue = (node**) malloc(sizeof(node*));
}
else{
p_queue->queue = (node**) realloc(p_queue->queue,sizeof(node*)*(p_queue->size+1));
}
p_queue->queue[p_queue->size] = x;
while(i>=0 && p_queue->queue[i]->amount < p_queue->queue[(i-1)/2]->amount){
node* temp = p_queue->queue[i];
p_queue->queue[i] = p_queue->queue[(i-1)/2];
p_queue->queue[(i-1)/2] = temp;
i = (i-1)/2;
}
p_queue->size++;
}
node* delete_min(priority_queue* p_queue){
node** queue = p_queue->queue;
node* min = queue[0];
if(p_queue->size>1){
int r = 0;
int current = 1; //left child of root
queue[0] = queue[p_queue->size-1];
queue = (node**) realloc(queue,sizeof(node*)*(--p_queue->size));
while(current < p_queue->size){
//in case of 2 children, check if current needs to be right or left child
if(current < p_queue->size-1 && queue[current] > queue[current+1]){
current++;
}
if(queue[current] < queue[r]){
node* temp = queue[r];
queue[r] = queue[current];
queue[current] = temp;
r = current;
current = 2 * current;
}
else{
break;
}
current++;
}
}
else{
free(queue);
p_queue->size--;
}
return min;
}
EDIT: Added the valgrind output:
编辑:添加了 valgrind 输出:
Invalid read of size 4
==1893== at 0x80498E0: delete_min (huffman.c:331)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd
==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1893== by 0x8049922: delete_min (huffman.c:335)
==1893== by 0x80492CC: huffman_encode (huffman.c:195)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893==
==1893== Invalid read of size 4
==1893== at 0x8049901: delete_min (huffman.c:333)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893== Address 0x441db64 is 444 bytes inside a block of size 452 free'd
==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1893== by 0x8049922: delete_min (huffman.c:335)
==1893== by 0x80492CC: huffman_encode (huffman.c:195)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893==
==1893== Invalid write of size 4
==1893== at 0x8049906: delete_min (huffman.c:333)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd
==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1893== by 0x8049922: delete_min (huffman.c:335)
==1893== by 0x80492CC: huffman_encode (huffman.c:195)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893==
==1893== Invalid free() / delete / delete[] / realloc()
==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1893== by 0x8049922: delete_min (huffman.c:335)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd
==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1893== by 0x8049922: delete_min (huffman.c:335)
==1893== by 0x80492CC: huffman_encode (huffman.c:195)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893==
==1893== Invalid read of size 4
==1893== at 0x8049A0E: delete_min (huffman.c:337)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1893==
==1893==
==1893== Process terminating with default action of signal 11 (SIGSEGV)
==1893== Access not within mapped region at address 0x0
==1893== at 0x8049A0E: delete_min (huffman.c:337)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
Line 331 is the line in delete_min of: node* min = queue[0];
第331行是delete_min中的一行:node* min = queue[0];
EDIT:
编辑:
The problem is solved now. In the accepted answer, the reason why is explained. Just assigning the realloced value correct, in delete_min solved all issues.
现在问题解决了。在接受的答案中,解释了原因。只是正确分配重新分配的值,在 delete_min 中解决了所有问题。
//realloc queue and assign new value to local queue var
p_queue->queue = (node**) realloc(queue,sizeof(node*)*(--p_queue->grootte));
queue = p_queue->queue;
回答by Noctua
I'll explain the first error to you.
我会向你解释第一个错误。
==1893== Invalid read of size 4
==1893== at 0x80498E0: delete_min (huffman.c:331)
==1893== by 0x80492DA: huffman_encode (huffman.c:196)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
At line 331, you're probably reading an (unsigned) int, in a part of the memory you haven't allocated for your own program.
在第 331 行,您可能正在读取一个(无符号的)int,位于您尚未为自己的程序分配的内存的一部分。
==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd
==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1893== by 0x8049922: delete_min (huffman.c:335)
==1893== by 0x80492CC: huffman_encode (huffman.c:195)
==1893== by 0x8049DDE: encode_file (main.c:94)
==1893== by 0x8049BBE: main (main.c:32)
==1893==
This part gives more information about the part of memory you tried to read. It says you've already used the memory, but reallox freed it. That means you're reading from an old pointer to a part of memory you've realloccated.
这部分提供了有关您尝试读取的内存部分的更多信息。它说你已经使用了内存,但是 reallox 释放了它。这意味着您正在从旧指针读取已重新分配的内存部分。
You should make sure you use the pointer realloc returns, and not the old one.
您应该确保使用指针 realloc 返回,而不是旧的。
The reason this doesn't crash when running outside valgrind, is that most of the time, the same part of memory will be allocated by realloc. So the pointer remains the same, and as such your code will work. However, sometimes, realloc will decide to move the part of the memory, and then your code will crash. Valgrind's trying to warn you for this.
在 valgrind 之外运行时不会崩溃的原因是,大多数情况下,realloc 将分配相同的内存部分。因此指针保持不变,因此您的代码将起作用。但是,有时,realloc 会决定移动这部分内存,然后您的代码就会崩溃。Valgrind 正试图就此警告您。
The rest of the errors will probably be solved when you're using the returned pointer.
当您使用返回的指针时,其余的错误可能会得到解决。
回答by 1''
Based on your Valgrind errors, you are probably accessing and then freeing nodes you've already deleted. You should consider posting the Valgrind errors with the corresponding line numbers (compile with -g in gcc) to make it easier for us to help you.
根据您的 Valgrind 错误,您可能正在访问并释放已删除的节点。您应该考虑发布带有相应行号的 Valgrind 错误(在 gcc 中使用 -g 编译),以便我们更轻松地为您提供帮助。
Edit: The most glaring error, the segfault, is where you should start debugging. This line fails:
编辑:最明显的错误,段错误,是你应该开始调试的地方。此行失败:
while((2*i)+2 < p_queue->grootte-1 && (queue[i]->amount > queue[(2*i)+1]->amount || queue[i]->amount > queue[(2*i)+2]->amount)){
presumably because queueis NULL. Why is it NULL? Probably because realloc didn't allocate anything. Why didn't it allocate anything? Either because you ran out of memory (unlikely) or because you tried to allocate something of size 0. (See http://www.cplusplus.com/reference/cstdlib/realloc/for details of realloc). How could you request size 0? If p_queue->size-1is 0.
大概是因为queue是NULL。为什么是NULL?可能是因为 realloc 没有分配任何东西。为什么它没有分配任何东西?要么是因为内存不足(不太可能),要么是因为您试图分配大小为 0 的内容。(有关realloc 的详细信息,请参阅http://www.cplusplus.com/reference/cstdlib/realloc/)。你怎么能要求0号?如果p_queue->size-1是 0。

