C 中使用 goto 进行错误处理

c 中使用 goto 进行错误处理

最近,Python Brasil 邮件列表上开始了关于使用异常的原因的讨论。有一次,一位非常有能力的参与者评论了通过函数返回来处理错误是多么困难,就像在 C 中一样。

当你有一个复杂的算法时,每个可能失败的操作都需要一系列的 if 来检查操作是否成功。如果操作失败,您需要恢复之前的所有操作以退出算法,而不改变程序的状态。

让我们看一个例子。假设我有以下结构来表示数组:

typedef 结构体 {    整数大小;    整数*数组;} array_t;

现在,我将编写一个函数,从文本文件中读取要放置在这些数组之一中的元素数量,然后读取元素本身。该函数还将分配数组结构和数组本身。问题是这个函数很容易出错,因为我们可能会失败:

打开给定的文件;分配结构体;由于输入/输出错误或文件结尾而读取给定文件中的元素数量;分配内存来存储要读取的元素;由于输入/输出错误或文件结尾而读取其中一个元素。

很复杂吧?请注意,如果我们设法打开文件但无法分配结构,则必须关闭该文件;如果我们设法打开文件并分配结构体,但无法从文件中读取元素数量,则必须释放结构体并关闭文件;等等。因此,如果我们检查所有错误并采用在出现错误时返回 NULL 的传统,我们的函数将如下所示:

array_t *readarray(const char *文件名) {    文件*文件;    array_t *数组;    整数我;    文件 = fopen(文件名, "r");    如果(文件== NULL)返回NULL;    数组= malloc(sizeof(array_t));    如果(数组== NULL){        fclose(文件);        返回空值;    }    if (fscanf(文件, "%d", &(数组->大小)) == EOF) {        自由(数组);        fclose(文件);        返回空值;    }    数组->数组 = malloc(sizeof(int) * 数组->大小);    if (数组->数组 == NULL) {        自由(数组);        fclose(文件);        返回空值;    }    for (i = 0; i 大小; i++) {        if (fscanf(文件, "%d", 数组->数组 + i) == EOF) {            自由(数组->数组);            自由(数组);            fclose(文件);            返回空值;        }    }    返回数组;}

确实,相当费力,而且有很多重复的代码……

但是请注意,上面的代码中有两种情况

其中,当我有两个操作要恢复时,我需要先恢复最后执行的一个,然后再恢复前一个。例如,当释放结构体和整数数组时,我需要先释放整数数组,然后释放结构体。如果我先释放结构体,以后可能无法释放数组。在其他情况下,顺序并不重要。例如,如果我要释放结构体并关闭文件,那么执行此操作的顺序并不重要。这意味着我也可以先恢复最后执行的操作,然后恢复第一个操作。

这有什么意义?嗯,在实践中,我从未见过必须先恢复第一个执行的操作,然后恢复第二个,依此类推的情况。这意味着,当执行操作 a()、b()、c() 等时,恢复它们的“自然”方法是以相反的顺序调用恢复函数,如下所示:

a();b();C();/* ... */revert_c();恢复b();恢复a();

现在窍门来了。在上面的代码中,在每个操作之后,我们都会放置一个 if 来检查它是否失败。如果失败,将执行 goto 到上次成功操作的恢复函数:

a();if (failed_a()) 转到 FAILED_A;b();if (failed_b()) 转到 FAILED_B;C();if (failed_c()) 转到 FAILED_C;/* ... */revert_c();失败_C:恢复b();失败_B:恢复a();失败_A:返回;

如果a()失败,算法返回;如果 b() 失败,算法将转到 FAILED_B:,恢复 a() 并返回;如果 c() 失败,算法将转到 FAILED_C,恢复 b(),恢复 a(),然后返回。你能看到图案吗?

如果我们将此模式应用于 readarray() 函数,结果将类似于:

array_t *readarray(const char *文件名) {    文件*文件;    array_t *数组;    整数我;    文件 = fopen(文件名, "r");    如果(文件== NULL)转到FILE_ERROR;    数组= malloc(sizeof(array_t));    如果(数组== NULL)转到ARRAY_ALLOC_ERROR;    if (fscanf(文件, "%d", &(数组->大小)) == EOF)        转到SIZE_READ_ERROR;    数组->数组 = malloc(sizeof(int) * 数组->大小);    if (array->array == NULL) 转到 ARRAY_ARRAY_ALLOC_ERROR;    for (i = 0; i 大小; i++) {        if (fscanf(文件, "%d", 数组->数组 + i) == EOF)            转到 ARRAY_CONTENT_READ_ERROR;    }    返回数组;    ARRAY_CONTENT_READ_ERROR:    自由(数组->数组);    ARRAY_ARRAY_ALLOC_ERROR:    大小读取错误:    自由(数组);    ARRAY_ALLOC_ERROR:    fclose(文件);    文件错误:    返回空值;}

这种模式有什么优点?嗯,它减少了操作反转代码的重复,并将错误处理代码与功能逻辑分离。事实上,虽然我认为异常是最好的现代错误处理方法,但对于本地错误处理(在函数本身内部),我发现这种方法更实用。

(这篇文章是 Tratamento de error em C com goto 的翻译,最初发表于 Suspensão de Descrença。)

以上就是C 中使用 goto 进行错误处理的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1455385.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月18日 07:43:23
下一篇 2025年12月14日 14:38:42

相关推荐

  • 实现 malloc() 和 free() — 将元数据添加到内存块

    这篇文章是关于实现 malloc() 和 free() 函数的系列文章的一部分。之前,我们实现了一种相当简单的方法,几乎​​不释放任何内存:一个指针指向最后分配的块,使 free() 能够释放它,但只能释放它。 更好的选择是让最后一个块指向倒数第二个块,倒数第二个块指向倒数第三个块,依此类推,形成一…

    2025年12月18日
    000
  • 踏上为期一年的软件工程之旅:从 C 到 Python、JavaScript、Node.js、DevOps 等

    踏上为期一年的软件工程之旅:从 C 到 Python、JavaScript、Node.js、DevOps 等 欢迎各位编码爱好者,踏上广阔而动态的软件工程领域的激动人心的旅程!在接下来的 365 天里,我们将踏上一场变革性的冒险之旅,穿越 C、Python、JavaScript、Node.js、De…

    2025年12月18日
    000
  • 【Linux的历史】:第一种编程语言和第一个操作系统的起源

    随着第一个用于解释机械指令的复杂系统的出现,需要创建命令行,以便这些相同的机器可以根据给出的命令和/或已经预先保存的命令(存储或已编程)供机器执行。 #include #include #include // 定义表示进程和内存的结构体typedef 结构体过程{ 整数ID; int 执行时间; i…

    2025年12月18日
    000
  • C++框架在未来技术中的应用场景有哪些?

    c++++ 框架在未来技术中发挥着重要作用,特别是在 ai(tensorflow、pytorch、caffe)、hpc(openmp、mpi、cuda)、云计算(cassandra、hadoop、spark)和嵌入式系统(μc/os-ii、freertos、arduino framework)等领域…

    2025年12月18日
    000
  • C++框架与其他流行框架(如Python、Java)相比有何优劣势?

    c++++ 框架在性能、内存效率和灵活性方面胜过 python 和 java 框架,但它具有陡峭的学习曲线和缺乏动态性。优势:性能卓越内存效率灵活跨平台支持劣势:陡峭的学习曲线缺乏动态性缺乏社区支持 C++ 框架与其他流行框架(Python、Java)的优劣势 引言 C++ 是一种强大的编程语言,拥…

    2025年12月18日
    000
  • C++框架与其他语言框架的比较

    c++++ 框架以性能、类型安全和可扩展性著称,而其他语言框架(如 python django、java spring framework 和 javascript angular)则更注重易用性和跨平台支持。实战案例表明,c++ 框架适用于高性能科学计算和跨平台桌面应用程序,而 python 和 …

    2025年12月18日
    000
  • 特定领域C++框架与其他编程语言框架的比较

    c++++ 框架以其高性能、内存控制和跨平台支持而著称,但也存在陡峭的学习曲线、手动内存管理和较少的高级功能。python、java 和 node.js 框架分别以其简洁性、面向对象性和高并发性而闻名,适合不同应用场景,如数据科学、企业级应用和服务器端开发。选择框架时,应根据应用需求、团队技能、性能…

    2025年12月18日
    000
  • 哪些C++框架最适合移动开发?

    最佳 c++++ 移动开发框架:qt:功能丰富、易用、高性能,适用于桌面、移动和嵌入式应用程序。juce:轻量跨平台框架,专为音频和多媒体应用设计,适用于音乐制作软件、音频工具。cocos2d-x:开源游戏开发框架,支持多种语言,适合各种移动游戏开发。unreal engine:高保真游戏开发引擎,…

    2025年12月18日
    000
  • C++框架与其他语言框架的对比

    c++++ 框架以其速度和细粒度控制著称,但学习曲线较陡峭。与其他语言框架相比:python:c++ 速度更快,但 python 更易读且采用自动内存管理。java:c++ 通常更快,但 java 跨平台性更好且采用自动内存管理。在需要高性能、细粒度控制且不需要跨平台性的项目中,c++ 框架更合适。…

    2025年12月18日
    000
  • 依赖项管理在C++框架中扮演什么角色?

    在 c++++ 框架中使用依赖项管理工具可以带来诸多好处,包括自动解析和安装依赖项、确保版本一致性、管理冲突和提升开发效率。流行的依赖项管理工具包括 conan、cmake、hunter 和 vcpkg。本文以使用 conan 管理依赖项为例,展示了在 c++ 框架中实际使用依赖项管理工具的步骤。 …

    2025年12月18日
    000
  • 采用 C++ 框架在大型项目中管理依赖关系和集成问题

    在大型 c++++ 项目中,框架提供了以下工具管理依赖关系和集成:依赖关系管理使用包管理系统(如 cmake、conan)定义和自动化依赖项的下载、构建和安装。集成遵循特定步骤和惯例,如分层架构,实现组件松耦合和简化通信。通过使用这些工具,团队可以高效地构建和维护大型、模块化的 c++ 项目。 在大…

    2025年12月18日
    000
  • C++ 框架与其他语言框架有何区别?

    c++++框架在结构和类型安全、指针和引用、范式支持、性能和内存管理方面与其他语言框架不同。它提供静态类型安全、指针和引用支持、多范式支持、高性能以及手动内存管理。与python和javascript等使用动态类型或垃圾收集器的语言框架相比,c++框架更注重类型安全和直接硬件访问,从而提供更好的性能…

    2025年12月18日
    000
  • C++ 框架性能基准:工具和技术的使用

    对于 c++++ 框架的性能基准测试,本文介绍了 google benchmark 和 cpp-benchmark 等工具,以及 microbenchmarks 和 macrobenchmarks 等技术。通过比较每个迭代的时间、每秒操作数 (ops) 和错误率等性能指标,您可以评估不同框架的性能。…

    2025年12月18日
    000
  • C++ 框架在制药行业的应用:加速药物开发与临床研究

    c++++ 框架在制药行业中发挥着至关重要的作用,它提供卓越的性能、灵活性和可扩展性。这些优势体现在以下应用中:药物发现:分子动态模拟和虚拟筛选。临床研究:临床数据管理和统计分析。监管合规性:电子病历和药物警戒。 C++ 框架在制药行业的应用:加速药物开发与临床研究 引言 C++ 是一种强大且灵活的…

    2025年12月18日
    000
  • C++ 框架性能基准:与其他语言和平台的比较

    基准测试结果表明,c++++ 框架在 http 请求处理和数据库查询方面表现优异,boost.asio 适用于高并发连接,cpp-httplib 和 libuv 具有较低延迟。开发人员应根据不同场景选择最合适的框架。 C++ 框架性能基准:与其他语言和平台的比较 引言 性能是任何软件应用程序的关键方…

    2025年12月18日
    000
  • C++ 框架社区资源的可持续发展

    策略:持续支持基础设施(托管平台、文档站点、问题跟踪系统)鼓励文档贡献支持多元化贡献(初学者、不同背景)促进代码质量(代码审查、单元测试、持续集成)建立治理结构(协调工作、设定优先级)实战案例:boost.python:指导委员会、捐款、志愿者、文档黑客马拉松、代码审查qt:非营利基金会、认证计划、…

    2025年12月18日
    000
  • C++ 框架与其他语言框架在游戏开发中的性能对比

    c++++ 框架在游戏开发中性能最佳,因为它直接与硬件交互,开销最小。相比之下,java、c# 和 python 框架在虚拟机上运行,增加了开销,导致性能下降。此外,python 框架由于其动态类型和解释执行,性能最低。因此,对于需要高性能的游戏,c++ 框架是最佳选择。 C++ 框架与其他语言框架…

    2025年12月18日
    000
  • C++ 框架在性能上的优势与其他语言框架的对比

    c++++ 框架在性能上具有多重优势:零开销抽象、低级内存管理和高效的数据结构和算法。与 java 和 python 框架相比,c++ 框架由于其编译性质和内存控制而更快,与 go 框架类似,但后者具有更好的垃圾回收机制。 C++ 框架在性能上的优势 在现代软件开发中,框架扮演着至关重要的角色。它们…

    2025年12月18日
    000
  • C++ 框架与其他语言框架在大型项目的复杂性对比

    c++++ 框架在大项目中通常比其他语言框架更复杂,因为它是一种静态类型化语言,依赖于模版和宏;而其他语言框架通常更简单,因为它使用动态类型化和提供丰富的库。 C++ 框架与其他语言框架在大型项目的复杂性对比 随着软件项目规模的不断扩大,选择正确的框架变得至关重要。在大型项目中,框架可以帮助我们组织…

    2025年12月18日
    000
  • C++ 框架在桌面和移动应用开发中的选择差异,与其他语言框架的权衡

    桌面应用:qt、wxwidgets、mfc;移动应用:react native、nativescript;权衡:python、java、c#易学但开销高;.net、java特定平台;javascript易学但性能受限。基于需求和平台选择最佳框架:库存管理(桌面)用qt;找餐厅应用(移动)用react…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信