背景:
我正在尝试从 .goo 文件(Elegoo Mars 4 的 SLA 打印机文件格式)解析图层信息。
3D 模型的每一层都编码在存储在
goo_layer_definition[nlayers]
中的新二进制文件块中。
问题:
我的解析函数适用于第一个块。
goo_layer_definition[0]
的所有字段均已完美读取并打印出来。
然而,当我尝试读取第二块时出现了段错误。
即我在读入 goo_layer_definition[1]
时遇到错误。
对于第二个块,正确读取了 pause_flag 和 pause_position_z 值。 但是,读入 layer_position_z 的值完全错误,并且在文件二进制文件中的任何位置都找不到。
此错误读取发生在 fread() 函数上,其中错误的数据被读入缓冲区。
总结
我被困在第一个块如何能够正确读取所有字段,并且第二个块的一部分被正确读取,但相同的代码只是决定在第二个块中的同一点读取错误的数据。
当循环 i=1 时,问题出现在 fread_goo_layer_content() 中。 问题出现就行了
if(!fread_le(&dst->layer_position_z, sizeof(float), 1, fp) ) return 0;
有人对可能出现的问题有建议吗?
// main.c
...
FILE *p_fin = fopen(argv[1], "rb");
if(p_fin == NULL){
(void)PRINT_ERR("Failed to open %s\n\n", argv[1]);
return ENOENT;
}
...
goo_layer_content_t *goo_layer_contents;
if(!fread_goo_layer_content(&goo_layer_contents, &goo_header_info, p_fin)){
(void)PRINT_ERR("Failed to read content info for %s\n\n", argv[1]);
return EIO;
}
...
注意:fread_le() 只是 fread() 的包装,但转换为小端。
// goo.c
int fread_goo_layer_definition(goo_layer_definition_t *dst, FILE *fp){
if(!fread_le(&dst->pause_flag , sizeof(int16_t ), 1, fp) ) return 0;
if(!fread_le(&dst->pause_position_z , sizeof(float ), 1, fp) ) return 0;
if(!fread_le(&dst->layer_position_z , sizeof(float ), 1, fp) ) return 0;
if(!fread_le(&dst->layer_exposure_time , sizeof(float ), 1, fp) ) return 0;
if(!fread_le(&dst->layer_off_time , sizeof(float ), 1, fp) ) return 0;
...
return 1;
}
int fread_goo_layer_content(goo_layer_content_t **dst, goo_header_info_t *header, FILE *fp){
// Jump to layer content segment
if(fseek(fp, header->offset_of_layer_content, SEEK_SET)) return 0;
*dst = (goo_layer_content_t*)calloc(header->total_layers, sizeof(goo_layer_content_t));
if(*dst == NULL) return 0;
// Loop through all layers and read their layer info
for(int i=0; i < header->total_layers; i++){
// Reading layer definition
if(!fread_goo_layer_definition(&dst[i]->definition, fp) ) return 0;
// Reading image data
...
}
return 1;
}
//goo.h
#pragma packed
typedef struct goo_layer_definition_t {
int16_t pause_flag ; //
float pause_position_z ; //
float layer_position_z ; //
float layer_exposure_time ; //
float layer_off_time ; //
float before_lift_time ; //
float after_lift_time ; //
float after_retract_time ; //
float lift_distance ; //
float lift_speed ; //
float second_lift_distance ; //
float second_lift_speed ; //
float retract_distance ; //
float retract_speed ; //
float second_retract_distance ; //
float second_retract_speed ; //
int16_t light_pwm ; //
uint16_t delimiter ; //
} goo_layer_definition_t;
#pragma packed
typedef struct goo_layer_content_t {
goo_layer_definition_t definition ; // Layer definitions
int32_t data_size ; // Indicate size of image_data
uint8_t data_start ; // Fix value: 0x55
image_data_chunk_t *image_data ; // See spec PDF
uint16_t delimiter ; // Fix value: 0x0D_0A
} goo_layer_content_t;
调试尝试:
我查看了 GDB 和十六进制编辑器并单步执行了每个 fread()。存储在缓冲区中的值在读取第二个块之前都是正确的
fread_le(&dst->layer_position_z...)
.
我还尝试打印每次读取的 fgetpos() ,并且位置以每次读取的正确量递增,即 u16 为 2 个字节,float 为 4 个字节。
我还将 fgetpos() 位置值与十六进制编辑器的地址偏移量进行了比较,并将其数据排列起来,直到读取第二个块上的 layer_position_x 为止。
即
我在十六进制编辑器中看到的内容:
correct datas ... 0A 8C 8D 1E 0D 0A 00 00 3C A3 D7 0A *3C A3 D7 0A*
我从 fread() 得到什么:
correct datas ... 0A 8C 8D 1E 0D 0A 00 00 3C A3 D7 0A *40 A3 D7 0D*
前面的204168字节都是正确的。 错误发生在地址 204172 上——我不确定这是否是对 fread() 的限制。 错误是一致的,每次运行都会在同一点读取相同的错误值。
我还检查了 GDB 中的 calloc() 值是否正确。我的 1 层测试文件为 1,2 层测试文件为 2。
预计:
我期望 fread() 将 3C A3 D7 0A 读入缓冲区,而不是 40 A3 D7 0D。
&dst[i]->definition
中的 fread_goo_layer_definition
应该是 &(*dst)[i].definition
。
首先是
(*dst)
,就像函数中的所有其他用途一样,然后是索引。