gpt4 book ai didi

c - 当函数返回时,如何在C中关闭资源句柄?

转载 作者:行者123 更新时间:2023-11-30 20:20:10 26 4
gpt4 key购买 nike

如果我打开一个文件句柄,但函数遇到其他非文件错误的错误,在关闭句柄之前,文件句柄会泄漏吗?

FILE* fp = fopen("test.txt", "r");
if (other_condition) {
perror("other error occurred!");
return EXIT_FAILURE;
}

如何用C实现RAII模板?

最佳答案

对于像文件句柄这样的单一资源,请考虑:

int rc = EXIT_FAILURE;
FILE *fp = fopen(file, "r");
if (fp != NULL)
{
rc = function_using_resource(fp /* , … */);
fclose(fp);
}
else
{
perror(file);
}
return rc;

仅在成功分配资源时才使用该资源,并从使用已分配资源的函数返回状态。该函数打开文件;它负责关闭它。如果它被打开,它会关闭它。

这样做的缺点是,您最终会得到很多单独的函数并不是很大。然而,将其扩展到多种资源是很困难的。您可能最终会使用 goto,但这是一种精心构造的用法。例如,考虑打开文件流并分配两个内存块的代码。您最终可能会得到如下代码:

int function_example(int num_items)
{
int rc = EXIT_FAILURE;
struct WotNot *wotsit = NULL;
struct Havoc *wreaker = NULL;
FILE *fp = fopen(file, "r");

if (fp == NULL)
{
err_remark("failed to open file '%s' for reading\n", file);
goto cleanup;
}

if ((wotsit = malloc(num_items * sizeof(*wotsit))) == NULL)
{
err_remark("failed to allocated %zu bytes of memory\n",
num_items * sizeof(*wotsit));
goto cleanup;
}

if ((rc = function_using_file(fp, num_items, wotsit)) != EXIT_SUCCESS)
{
err_remark("processing of wotsits failed\n");
goto cleanup;
}

if ((wreaker = malloc(num_items * 2 * sizeof(*wreaker)) == NULL)
{
err_remark("failed to allocated %zu bytes of memory\n",
num_items * 2 * sizeof(*wreaker));
goto cleanup;
}

if ((rc = function_wreaking_havoc(num_items, wotsit, wreaker) != EXIT_SUCCESS)
{
err_remark("failed to wreak appropriate havoc\n");
goto cleanup;
}

if ((rc = other_function(fp, num_items * 2, wreaker)) != EXIT_SUCCESS)
{
err_remark("failed to process the wotsits — not enough havoc?\n");
goto cleanup; // Systematic, but nominally superfluous
}

cleanup:
free(wreaker);
free(wotsit);
if (fp != NULL)
fclose(fp);
return rc;
}

请注意资源如何初始化为无害状态(空指针)。如果出现问题,代码会跳转到清理 block 。 free() 函数优雅地接受空指针并且不执行任何操作,因此这些调用不需要检查,但 fclose() 不一定在给定空指针的情况下干净地工作指针,因此在调用 fclose() 之前检查文件流。

这是一个相当常见的习语。变体包括针对不同数量的清理工作的多个标签。当您没有在此函数中放置太多事件来代替显示的执行工作的函数调用时,这一点仍然是最清楚的。然而,除了资源分配之外,在函数中完成的工作并不罕见——通常包括工作负载的计算部分,特别是当涉及动态增长一个或多个分配的数组等工作时。像这样混合起来仍然不是一个特别好的主意,但这并不能阻止人们这样做。

对于被调用函数报告错误还是调用函数报告错误,或者两者都不报告,您应该有一个约定。您还可以使用各种机制来构建错误报告。确保尽可能轻松地处理错误非常重要 - 这意味着人们不太可能在错误报告上吝啬。

其他相关问题包括:

等等

关于c - 当函数返回时,如何在C中关闭资源句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47320989/

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