我正在尝试读取具有以标识符开头的块的二进制文件(如3DS文件)。我遍历文件并使用开关,程序确定块具有什么标识符,然后将数据读入文件结构。有时我需要使用malloc为动态大小的数据分配内存。在读取时,交换机经常会分配内存的相同情况,但是在文件中的特定点,它会在同一个malloc上崩溃。我想读的文件大约是1MB。但是当我用另一个大约10kB的文件和相同的结构来尝试该程序时,它会成功地读取它。
可能导致此问题的原因是什么?
调试时得到的错误代码是:
Heap corruption detected at 0441F080
HEAP[prog.exe]: HEAP: Free Heap block 441f078 modified at 441f088 after it was freed
当我在调试模式下执行它时,出于某种原因我可以从文件中读取更多数据。该程序在崩溃之前会持续更长时间。
以下是代码崩溃的代码:
switch (id) {
case 0x62:
case 0x63:
// ...
{
char n_vertices = id - 0x60 + 1;// just how I calculate the n_vertices from the block ID
fread(&mem.blocks[i].data.attr_6n.height, 2, 1, f);
mem.blocks[i].data.attr_6n.vertices = malloc(2 * n_vertices);// crash
for (short k = 0; k < n_vertices; k++) {
fread(&mem.blocks[i].data.attr_6n.vertices[k], 2, 1, f);// read shorts
}
}
break;
// ...
}
答案 0 :(得分:8)
你可能有一个腐败的堆。这可能是由无效的解除分配(解除分配无主或已经空闲的内存)引起的,或者是由一些随机的代码块写入其内存区域之外的一个地方,而这个地方恰好占据了堆bookeeping数据结构。这很可能是一段与动态分配的内存无关的代码。
追踪像这样的错误是一个真正的熊。它们往往会在违规代码执行后很长时间内出现,而且它们会变成heisenbugs(当你试图调试它们时会移动或消失的错误)。(/ p>
我接近调试的建议是尝试注释掉部分代码,看看导致问题消失的原因。这不是万无一失的,因为你最终可能会将越界写入其他地方。
查看您刚刚发布的代码,我强烈要求高度建议您验证您的malloc
指定了足够的内存来保存您尝试加载到其中的所有数据。在我看来,你假设每个顶点有2个字节。这对我来说似乎有点怀疑。我不知道你的代码,但是4或8将是更常见的元素大小。无论如何,行业惯例是在目标类型上使用sizeof()
来帮助确保您正确使用它。
另一个选项,如果您的调试器消息可以显示它发生的位置,那就是在调试器中放置一个调试器观察点(或写一些观察代码......或者手动转储并检查该区域)调试器试图弄清楚哪一行是有问题的代码。
祝你好运。我讨厌这些错误。答案 1 :(得分:3)
很可能堆以某种方式损坏了,malloc崩溃,例如试图遍历一个损坏的空闲块链接列表(或类似的结构,我现在还不确定现代堆分配器中使用的是什么)。
确保您的代码没有写入已分配块的末尾。
答案 2 :(得分:0)
您需要在valgrind
等内存调试器中运行它。由于您看起来像是在Windows上,请参阅以下内容:Is there a good Valgrind substitute for Windows?