gpt4 book ai didi

c - 处理来自多个 fread 调用的错误的更简洁的方法

转载 作者:太空狗 更新时间:2023-10-29 15:28:24 24 4
gpt4 key购买 nike

我在 C 中有以下方法来加载二进制文件,必须检查每个 fread 调用的错误值似乎相当冗长乏味,有没有更简洁的方法来处理这个问题?

我知道可以通过一次读取结构来减少一些调用,但由于 C 可以在结构成员之间添加填充字节,我宁愿避免这种情况。

some_type_t *load_something(FILE *file) {
some_type_t *something = (some_type_t *)malloc(sizeof(some_type_t));
if (something == NULL) {
return NULL;
}

if (fread(&something->field1, sizeof(something->field1), 1, file) == 0) {
free(something);
return NULL;
}
if (fread(&something->field2, sizeof(something->field2), 1, file) == 0) {
free(something);
return NULL;
}
if (fread(&something->field3, sizeof(something->field3), 1, file) == 0) {
free(something);
return NULL;
}

uint16_t some_var1, some_var2, some_var3;

some_other_type_t *something_else1 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var1, sizeof(some_var1), 1, file) == 0) {
free(something);
free(something_else1);
return NULL;
}

some_other_type_t *something_else2 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var2, sizeof(some_var2), 1, file) == 0) {
free(something);
free(something_else1);
free(something_else2);
return NULL;
}

some_other_type_t *something_else3 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var3, sizeof(some_var3), 1, file) == 0) {
free(something);
free(something_else1);
free(something_else2);
free(something_else3);
return NULL;
}
// Do something with the vars and allocated something elses.
// ...

return something;
}

最佳答案

为什么不创建一个宏:

#define READ_FIELD(data) \
do { if (fread(&data, sizeof(data), 1, file) == 0) { \
free(something); \
free(something_else1);
free(something_else2);
return NULL; \
} } while(0)

然后像函数调用一样调用它:

READ_FIELD(something->field1);
READ_FIELD(something->field2);

READ_FIELD(some_var1);
READ_FIELD(some_var2);

代码将是相同的,但至少它现在是生成的而不是复制/粘贴的(可能有错误)。

宏必须在所有可能的内存块上调用 free,即使是那些尚未分配的内存块。唯一的约束是将未分配的设置为 NULL,这样 free 就不会崩溃。并且要 super 安全地更改为:

free(something); something = NULL;

(当然,如果 something 是分配指针的副本,设置为 NULL 并不能防止双重释放,它有限制)

您也可以将此技术应用于写入端,并且由于 M Oehm 建议,您可以在包装器宏中列出要读取/写入的内容:

#define DO_ALL \
DO_FIELD(something->field1); \
DO_FIELD(something->field2); \
DO_FIELD(some_var1); \
DO_FIELD(some_var2)

然后将DO_FIELD定义为READ_FIELDWRITE_FIELD:

#define DO_FIELD READ_FIELD
DO_ALL;
#undef DO_FIELD

关于c - 处理来自多个 fread 调用的错误的更简洁的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45564424/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com