我有一段代码看起来几乎像这样(这被简化只是为了显示结构):
int Ugly_Calculation(void)
{
type1 *X1 = type1_new();
if (!X1) return 0;
type2 *X2 = type2_new(X1);
if (!X2) return 0;
type3 *X3 = type3_new(X1, X2);
if (!X3) return 0;
int result = PerformCalculation(X1, X2, X3);
free(X3);
free(X2);
free(X1);
return result;
}
它分配一些对象并将它们用于某些计算并释放对象。 typeX_new 函数经常返回零,因此内存通常没有被正确释放。
在我的第一次迭代中,我按以下方式重写了代码:
typedef struct
{
type1 *X1;
type2 *X2;
type3 *X3;
} ugly_context;
void free_ctx(ugly_context *ctx)
{
free(ctx->X1);
free(ctx->X2);
free(ctx->X3);
}
int Ugly_Calculation(void)
{
ugly_context ctx = {NULL, NULL, NULL};
ctx->X1 = type1_new();
if (!ctx->X1)
{
free_ctx(&ctx);
return 0;
}
ctx->X2 = type1_new(ctx->X1);
if (!ctx->X2)
{
free_ctx(&ctx);
return 0;
}
ctx->X3 = type1_new(ctx->X1, ctx->X2);
if (!ctx->X3)
{
free_ctx(&ctx);
return 0;
}
int result = PerformCalculation(X1, X2, X3);
free_ctx(&ctx);
return result;
}
我的第一个修复是安全的,但它失去了原始代码的可读性。 我的第二个想法如下:
type2 *type2_new_check(type1 *X1)
{
type2 *result = NULL;
if (X1)
{
result = type2_new(X1);
}
return result;
}
type3 *type3_new_check(type1 *X1, type2 *X2)
{
type3 *result = NULL;
if (X1 && X2)
{
result = type3_new(X1, X2);
}
return result;
}
int PerformCalculation_check(type1 *X1, type2 *X2, type3 *X3)
{
int result = 0;
if (X1 && X2 && X3)
{
result = PerformCalculation(X1, X2, X3);
}
return result;
}
int Ugly_Calculation(void)
{
type1 *X1 = type1_new();
type2 *X2 = type2_new_check(X1);
type3 *X3 = type3_new_check(X1, X2);
int result = PerformCalculation_check(X1, X2, X3);
free(X3);
free(X2);
free(X1);
return result;
}
代码可读性还可以,早期退出也没有了,但是对于有 3 个内存块的方法来说它相当长。
我的真实代码不是 3 次分配,而是 15 次分配,因此该方法变得非常令人毛骨悚然和丑陋。有什么好的方法,如何在不进行过多检查和释放的情况下解决这种模式? (最好的方法是将方法分解为更小的部分,这些部分可以通过检查清楚地管理,但出于某种原因我想避免这种情况)
最佳答案
这是 goto
的(恕我直言)一个很好的用途(和一个常见的 C 习语):
type *obj1 = 0;
type *obj2 = 0;
type *obj3 = 0;
if (!(obj1 = create1())) goto error;
if (!(obj2 = create2())) goto error;
if (!(obj3 = create3())) goto error;
// your logic here
return 0; // success
error:
free(obj3);
free(obj2);
free(obj1);
return -1; // failure
或者,如果您还需要在成功案例中释放分配的资源,如下所示:
type *obj1 = 0;
type *obj2 = 0;
type *obj3 = 0;
int success = -1;
if (!(obj1 = create1())) goto error;
if (!(obj2 = create2())) goto error;
if (!(obj3 = create3())) goto error;
success = 0; // success
// your logic here
error:
free(obj3);
free(obj2);
free(obj1);
return success;
关于c - 可能会失败的分配和操作顺序的正确模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45715762/