Zed调试宏 C语言错误日志 异常错误调试信息

1、C中的错误码     

        在C语言中通过返回错误码或设置全局的errno值来反馈错误问题。errno.h是一个头文件,它定义了一个全局变量errno,用于在程序中记录和报告错误的原因。这个机制主要用于处理系统调用或标准库函数出错时的错误反馈。当系统调用或库函数遇到错误时,它通常不会直接返回错误信息,而是通过设置errno的值来告知程序具体的错误原因。
        errno在每个程序运行时由操作系统维护。它的值代表了最后一次系统调用或标准库函数失败时的错误类型。每当某个系统调用或库函数返回错误时,errno就会被设置为一个与错误相关的特定值。

错误码errno的值是一个整数,它对应着不同的错误类型,每种错误都有一个对应的宏定义。这些宏通常定义在errno.h文件中,例如:

  • EINVAL:无效参数。
  • ENOMEM:内存不足。
  • EIO:输入输出错误。
  • EBADF:文件描述符无效。
  • EACCESS:没有权限访问文件

        这些宏是常量值,为负值,每个宏的名字对应一个特定的错误情况。 当某个函数调用失败并且设置了errno后,程序可以通过检查errno的值来确定错误的类型。常用的做法是调用perror()或者strerror()来输出错误信息。

  • perror():它会根据errno的值打印出对应的错误消息,并且可以在错误信息前添加一个自定义的描述字符串。例如:
     

    perror("Error opening file");
    

    这行代码会输出类似以下的错误信息:

    Error opening file: No such file or directory
    
  • strerror():它返回一个指向静态字符串的指针,表示与errno值对应的错误信息。例如:

    printf("Error: %s\n", strerror(errno));
    

 2、使用Zed来打印错误信息

         其它语言通过异常来解决这个问题,但是这些问题也会在C中出现(其它语言也一样)。在C中你只能够返回一个值,但是异常是基于栈的返回系统,可以返回任意值。C语言中,尝试在栈上模拟异常非常困难,并且其它库也不会兼容。

        解决方案是,使用一系列“调试宏”,它们在C中实现了基本的调试和错误处理系统。这个系统非常易于理解,兼容于每个库,并且使C代码更加健壮和简洁。

        它通过实现一系列转换来处理错误,任何时候发生了错误,你的函数都会跳到执行清理和返回错误代码的“error:”区域。你可以使用check宏来检查错误代码,打印错误信息,然后跳到清理区域。你也可以使用一系列日志函数来打印出有用的调试信息。

#ifndef __dbg_h__  // 如果没有定义 __dbg_h__,则开始宏定义,防止重复引用
#define __dbg_h__#include <stdio.h>   // 引入标准I/O库,用于输出日志信息。
#include <errno.h>   // 引入errno.h,用于访问错误代码(errno)。
#include <string.h>  // 引入string.h,用于处理字符串函数(例如strerror())。// 如果没有定义NDEBUG(即没有禁用调试信息),则定义debug宏。
// debug宏将输出当前文件和行号以及调试信息,方便调试时跟踪。
#ifdef NDEBUG
#define debug(M, ...)  // 如果定义了NDEBUG,则禁用调试输出
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)  
// 否则,输出调试信息,包括文件名、行号。
//##__VA_ARGS__,它告诉预处理器将...所在位置的参数注入到fprintf调用的相应位置
#endif// clean_errno宏:如果errno为0(表示没有错误),则返回"None";否则,返回通过strerror()获取的错误描述字符串。
#define clean_errno() (errno == 0 ? "None" : strerror(errno))// log_err宏:输出错误日志,格式为"[ERROR] (文件名:行号:errno描述) 错误信息"。
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)// log_warn宏:输出警告日志,格式为"[WARN] (文件名:行号:errno描述) 警告信息"。
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)// log_info宏:输出普通信息日志,格式为"[INFO] (文件名:行号) 信息"。
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)// check宏:检查条件A是否为真。如果不为真,输出错误信息并跳转到error标签。
// 它帮助简化了条件检查和错误处理。
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }// sentinel宏:用于关键错误发生时的直接跳转。类似于check宏,但通常用于不应继续执行的情况。
#define sentinel(M, ...)  { log_err(M, ##__VA_ARGS__); errno=0; goto error; }// check_mem宏:用于检查内存分配是否成功。如果分配失败,记录错误信息并跳转到error标签。
#define check_mem(A) check((A), "Out of memory.")// check_debug宏:类似于check宏,但它会在调试模式下打印调试信息,帮助在调试阶段追踪问题。
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }#endif  // 结束宏定义

        这段代码的作用是简化C语言项目中的错误处理、调试和日志记录。它通过一系列宏定义提供了易于使用的工具,帮助开发者在程序中更好地管理错误,输出调试信息,以及记录不同级别的日志。每个宏的具体作用如下:

  1. 调试功能 (debug):在调试模式下,通过输出当前文件名和行号以及给定的调试信息,帮助开发者定位和解决问题。NDEBUG宏通常用于控制是否开启调试信息输出,默认情况下在编译时禁用调试输出。

  2. 错误日志功能 (log_err, log_warn, log_info):分别用于输出错误、警告和信息日志。在输出时会附加当前文件名、行号及错误代码errno的描述,方便开发者快速定位问题。

  3. 条件检查 (check, check_mem, check_debug):这些宏用于检查某个条件是否为真,如果条件不满足,则记录错误信息并跳转到error标签。check_mem专门用于检查内存分配是否成功。check_debug则在调试模式下提供额外的信息输出,帮助在调试时更清楚地了解程序的执行状态。

  4. 错误处理 (sentinel)sentinel可以放在函数的任何不应该执行的地方,它会打印错误信息并且跳到error:标签。你可以将它放到if-statements或者switch-statements的不该被执行的分支中,比如default

  5. clean_errno:这个宏用于清理errno的值,如果没有错误,返回"None";如果有错误,返回对应的错误信息。用于获取errno的安全可读的版本

         是的,仅仅22行的代码就可以充当一个错误日志打印的插件,可以完成简化错误处理、日志记录和调试过程,让代码更加清晰和易于维护。并且通过goto error 控制程序的流程,在出现错误时跳转到一个名为 error 的标签。通过使用 goto,程序会跳过剩余的正常流程,直接转到错误处理代码部分。这种做法通常用于清理资源和终止程序执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/64914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring mvc | servlet :serviceImpl无法自动装配 UserMapper

纯注解SSM整合 解决办法&#xff1a; 在MybatisConfig添加 Configuration MapperScan("mapper")

分布式协同 - 分布式事务_TCC解决方案

文章目录 导图Pre流程图2PC VS 3PC VS TCC2PC&#xff08;Two-Phase Commit&#xff0c;二阶段提交&#xff09;3PC&#xff08;Three-Phase Commit&#xff0c;三阶段提交&#xff09;TCC&#xff08;Try-Confirm-Cancel&#xff09;2PC、3PC与TCC的区别2PC、3PC与TCC的联系 导…

源码分析之Openlayers中MousePosition鼠标位置控件

概述 本文主要介绍 Openlayers 中的MousePosition鼠标位置控件&#xff0c;该控件会创建一个元素在页面的右上方用来实时显示鼠标光标的位置坐标。该控件在实际应用很有效&#xff0c;可以实时获取鼠标位置&#xff0c;但是一般控件元素都会自定义。 源码分析 MousePosition…

脑肿瘤检测数据集,对9900张原始图片进行YOLO,COCO,VOC格式的标注

脑肿瘤检测数据集&#xff0c;对9900张原始图片进行YOLO&#xff0c;COCO&#xff0c;VOC格式的标注 数据集分割 训练组 70&#xff05; 6930图片 有效集 20&#xff05; 1980图片 测试集 10&#xff05; 990图片 预处理 静态裁剪&#xff1a; 24-82&…

SQL进阶技巧:如何计算商品需求与到货队列表进出计划?

目录 0 需求描述 1 数据准备 2 问题分析 3 小结 累计到货数量计算 出货数量计算

步进电机接线和stm32引脚分配

实验设备 24v&#xff08;12-48 v&#xff09;直流电源 stm32f103最小系统板 步进电机驱动器 采用混合式二相步进电机J-5718HBS2401-野火42步进电机&#xff0c;驱动器为野火EBF-MSD4805 本人参考接线方式如下&#xff1a; 如上图所示通常采用共阴接线方式&#xff0c;具体…

极乐 15.2.6 | 清爽版简约美观音乐软件,支持网易云歌单导入

极乐是一款使用起来非常轻松的音乐播放软件&#xff0c;它拥有清新简洁的画面&#xff0c;专注于音乐播放功能。最新版本全面升级了64位架构&#xff0c;带来了前所未有的性能提升和更稳定的体验。通过优化内存管理&#xff0c;降低了应用对系统资源的占用&#xff0c;确保设备…

Ubuntu Netlink 套接字使用介绍

Netlink 套接字 是 Linux 特有的一种 IPC&#xff08;进程间通信&#xff09;机制&#xff0c;用于用户态进程和内核模块之间的通信。它可以用来完成路由管理、设备通知、网络状态更新等任务。 1. Netlink 的基本工作原理 Netlink 是一种双向通信机制。Netlink 消息分为请求和…

4、mysql高阶语句

mysql高阶语句是对复杂的条件进行查询的操作。 排序—order by 加了desc表示由大到小 1、查询name和score&#xff0c;地址都是云南西路的按id进行由小到大排序 2、查询name和score&#xff0c;先按hobbid进行排序&#xff0c;再把结果按id进行排序 第一段字段必须要有相同的…

Docker部署GitLab服务器

一、GitLab介绍 1.1 GitLab简介 GitLab 是一款基于 Git 的开源代码托管平台&#xff0c;集成了版本控制、代码审查、问题跟踪、持续集成与持续交付&#xff08;CI/CD&#xff09;等多种功能&#xff0c;旨在为团队提供一站式的项目管理解决方案。借助 GitLab&#xff0c;开发…

hadoop中hive本地模式安装mysql源不成功

目录 1.更改DNS配置 2.替换yun源 3.替换掉后&#xff0c;在执行 4.重新安装mysql源 hive本地模式安装mysql源出错 yum install mysql mysql-server mysql-devel -y 解决&#xff1a; 1.更改DNS配置 vi /etc/resolv.conf 添加下面内容&#xff1a; nameserver 8.8.8.8 …

深入解析 Apache APISIX

以下是“第一部分&#xff1a;背景与概述”的示例写作内容&#xff0c;供你参考和使用。你可根据实际需求和篇幅进行增删或细化。 一、背景与概述 1. 高性能动态网关的意义 1.1 微服务架构下的网关角色与价值 随着微服务架构在企业级应用中日益普及&#xff0c;系统被拆分为…

RISC-V架构的压缩指令集介绍

1、压缩指令集介绍 RISC-V的压缩指令集&#xff08;C扩展&#xff09;‌是一种设计用于减少代码大小和提高性能的技术。标准的RISC-V指令是32位&#xff0c;压缩指令集可以将部分32位的指令用16位的指令替代&#xff0c;从未减小程序占用存储空间的大小&#xff0c;提高指令密…

Day13 苍穹外卖项目 工作台功能实现、Apache POI、导出数据到Excel表格

目录 1.工作台 1.1 需求分析和设计 1.1.1 产品原型 1.1.2 接口设计 1.2 代码导入 1.2.1 Controller层 1.2.2 Service层接口 1.2.3 Service层实现类 1.2.4 Mapper层 1.3 功能测试 1.4 代码提交 2.Apache POI 2.1 介绍 2.2 入门案例 2.2.1 将数据写入Excel文件 2.2.2 读取Excel文…

齐次矩阵包含平移和旋转

第一个矩阵旋转矩阵 A [ R 1 0 0 1 ] A\left[\begin{matrix}R_{1} & 0\\0 & 1\end{matrix}\right] A[R1​0​01​] 第一个平移矩阵 B [ 1 T 1 0 1 ] B\left[\begin{matrix}1 & T_{1}\\0 & 1\end{matrix}\right] B[10​T1​1​] C [ R 2 0 0 1 ] C\left[\be…

CSP-X2024山东小学组T4:刷题

题目链接 CSP-X2024山东小学组T4&#xff1a;刷题 题目描述 比赛之路多艰&#xff0c;做题方得提升。努力刷题的人在比赛中往往能取得很好的成绩&#xff0c;小红就是这样的人。 为了继续提升自己的编程实力&#xff0c;小红整理了一份刷题题单&#xff0c;并选中了题单中的…

集星獭 | 高性能编排:为实时数据集成而生!

概要介绍 服务编排作为集星獭驱动业务流、数据流中不可或缺的重要环节&#xff0c;其基于分布式架构打造&#xff0c;提供了高可用、易扩展的可视化流程任务调度功能。 原服务编排的设计初衷是专注于任务调度&#xff0c;提供高性能任务调度&#xff0c;但是在实时调用方面的…

已有 containerd 的情况下部署二进制 docker 共存

文章目录 [toc]学习目的开始学习dockerd启动 containerd准备配置文件启动 containerd 启动 docker准备配置文件启动 docker 环境验证停止 docker 和 containerd 学习目的 使用容器的方式做一些部署的交付&#xff0c;相对方便很多&#xff0c;不需要担心别人的环境缺少需要的依…

高级java每日一道面试题-2024年12月20日-Spring篇-Autowired和Resource注解的区别?

如果有遗漏,评论区告诉我进行补充 面试官: Autowired和Resource关键字的区别? 我回答: 在Java高级面试中&#xff0c;Autowired和Resource是两个经常被提到的注解&#xff0c;它们主要用于Spring框架中的依赖注入。下面是对这两个注解的详细解释和它们之间的区别&#xff1…

达梦8-达梦数据的示例用户和表

1、示例库说明&#xff1a; 创建达梦数据的示例用户和表&#xff0c;导入测试数据。 在完成达梦数据库的安装之后&#xff0c;在/opt/dmdbms/samples/instance_script目录下有用于创建示例用户的SQL文件。samples目录前的路径根据实际安装情况进行修改&#xff0c;本文将达梦…