【发布时间】:2021-09-03 17:26:00
【问题描述】:
我有一个将常量结构写入二进制文件的程序。我需要它与以不同方式创建的另一个二进制文件完全匹配。但是,每次我运行我的可执行文件时,生成的二进制文件都是不同的。我需要每次生成的文件都相同。
重现问题的代码:
main.c:
#include <stdio.h>
typedef struct {
double vector1[3];
double vector2[3];
unsigned int a_uint32_field;
unsigned char a_uint8_field;
} Struct_type;
void CreateStruct(Struct_type* Struct_instance) {
Struct_instance->vector1[0] = 0.0;
Struct_instance->vector2[0] = 0.0;
Struct_instance->vector1[1] = 0.0;
Struct_instance->vector2[1] = 0.0;
Struct_instance->vector1[2] = 0.0;
Struct_instance->vector2[2] = 0.0;
Struct_instance->a_uint32_field = 0U;
Struct_instance->a_uint8_field = 0U;
}
int main() {
Struct_type Struct_instance;
FILE* file_pointer;
CreateStruct(&Struct_instance);
file_pointer = fopen("Saved_Struct.bin", "wb");
fwrite((void*)&Struct_instance, sizeof(Struct_instance), 1, file_pointer);
fclose(file_pointer);
return (0);
}
编译:
gcc -o executable main.c -m32 -O0
然后运行:
./executable
第一次运行,文件以十六进制\AE\CB\FF结尾,第二次是\F4\9C\FF。删除旧文件或让fopen 删除它似乎没有什么区别。它应该以全零结束,即:00\00\00
为什么会这样?我该如何预防?
【问题讨论】:
-
填充会伤害你 - 在读取和写入之前尝试将结构归零。类似
memset(&Struct_instance, 0, sizeof Struct_instance); -
也就是说,尝试在
CreateStruct的开头添加memset(Struct_instance, 0, sizeof(*Struct_instance))。 -
我想知道
Struct_type Struct_instance = {0};是否能解决问题?可能无法保证。 -
@yano 结构体所在堆栈上的垃圾数据。如果填充字节未初始化为任何内容,它们将保留此垃圾。
-
= {0}初始化程序会将填充初始化为全零位。请参阅 6.7.9/21,它说如果初始化器的数量少于结构成员,则结构的其余部分应像具有静态存储持续时间的对象一样初始化。并且 6.7.9/10 说 “如果它是一个聚合,则每个成员都根据这些规则进行初始化(递归),并且任何填充都初始化为零位;”
标签: c gcc binaryfiles