这是我正在使用的数组库中的代码片段。这在Windows上运行良好,但是如果我在Linux上使用gcc进行编译(如果该函数崩溃),则可以正常运行。当试图缩小问题范围时,我向其添加了一条printf语句,并且代码停止崩溃。
void _arrayCreateSize( void ***array, int capacity )
{
(*array) = malloc( (capacity * sizeof(int)) + sizeof(ArrayHeader) );
((ArrayHeader*)(*array))->size = 0;
((ArrayHeader*)(*array))->capacity = capacity;
// printf("Test!\n");
*(char**)array += sizeof(ArrayHeader);
}
Run Code Online (Sandbox Code Playgroud)
取出printf后,它再次开始崩溃。我完全不知道为什么会这样。
函数的最后一行没有按照预期执行。该代码难以理解。
看来目标是分配的数组int,因为sizeof(int)在第一个内存分配中。至少,如果要分配结构指针数组,则需要使用sizeof(SomeType *),某种指针类型的大小(sizeof(void *)可以)。如所写,这将在64位环境中严重失败。
该数组分配有一个结构头(ArrayHeader),后跟适当的数组。返回值应该在数组的开始处;可以通过从指针中减去来找到ArrayHeader。这是罪恶的丑陋现象,无法启动。它可以工作,但需要格外小心,而且(如Brian Kernighan所说)“如果编写代码时尽可能聪明,那么如何调试它?”。
不幸的是,最后一行是错误的:
void _arrayCreateSize( void ***array, int capacity )
{
(*array) = malloc( (capacity * sizeof(int)) + sizeof(ArrayHeader) );
((ArrayHeader*)(*array))->size = 0;
((ArrayHeader*)(*array))->capacity = capacity;
// printf("Test!\n");
*(char**)array += sizeof(ArrayHeader);
}
Run Code Online (Sandbox Code Playgroud)
它添加sizeof(ArrayHeader) * sizeof(char *)到地址,而不是预期的sizeof(ArrayHeader) * sizeof(char)。最后一行应为:
*(char *)array += sizeof(ArrayHeader);
Run Code Online (Sandbox Code Playgroud)
或者,如评论和替代答案中所述:
*(ArrayHeader *)array += 1;
*(ArrayHeader *)array++;
Run Code Online (Sandbox Code Playgroud)
我注意到,函数名称实际上不应以下划线开头。以下划线开头的外部名称保留给(C编译器和库)实现使用。
问题问“为什么printf()语句“修复”东西”。答案是因为它可以解决问题。您有一个Heisenbug,因为滥用了分配的内存,并且printf()管理程序的存在会稍微改变代码的行为。
valgrind。如果没有,请获取。malloc(),并返回指向分配数组结构的指针。| 归档时间: |
|
| 查看次数: |
3809 次 |
| 最近记录: |