首页 > 其他分享 >Zed调试宏 C语言错误日志 异常错误调试信息

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

时间:2024-12-23 23:30:47浏览次数:6  
标签:__ 错误 Zed errno 错误信息 调试信息 check log

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,程序会跳过剩余的正常流程,直接转到错误处理代码部分。这种做法通常用于清理资源和终止程序执行。

标签:__,错误,Zed,errno,错误信息,调试信息,check,log
From: https://blog.csdn.net/weixin_52342399/article/details/144678740

相关文章

  • 自建Anki服务器,并用AnkiDroid连接,解决error sending request for url()或用户名或密码
    说明参考:https://www.gerenbiji.com/blog/2024年/自建Anki同步服务器/官方文档:https://docs.ankiweb.net/sync-server.html环境:RockyLinuxx86平台方案:使用官方桌面客户端自带的服务器1.下载官方客户端https://apps.ankiweb.net/2.运行命令SYNC_USER1=[用户名1]:[明......
  • 别慌!msvcr110.dll丢失的解决方法来啦!有效解决msvcr110.dll错误
    在计算机系统的运行过程中,我们有时会遇到一些令人困扰的问题,其中“msvcr110.dll丢失”就是较为常见的一种情况。msvcr110.dll作为MicrosoftVisualC++RedistributablePackages的重要组成部分,对许多应用程序的正常运行起着关键作用。一旦该文件丢失,可能会导致一系列应用程序......
  • C语言常见错误总结
    语法错误 -括号不匹配:在函数定义、条件语句、循环语句等使用括号的地方,忘记添加或多添加括号,会导致编译错误。例如, if 语句中条件表达式括号不匹配,编译器会提示语法错误信息,指出缺少或多余的括号位置,仔细检查括号的成对性可避免。-分号缺失或多余:C语言语句以分号结束......
  • Tact智能合约安全实践:TON生态系统中的常见错误
    TON(TheOpenNetwork)以其创新特性和强大的智能合约性能,不断拓宽区块链技术的边界。基于早期的区块链平台(如以太坊等)的经验与教训,TON为开发者提供了一个更加高效且灵活的开发环境。其中推动这一进步的关键要素之一便是Tact编程语言。Tact是专为TON链设计的一种全新编程语言,以高......
  • 轻松解决《原地起啡》DLL错误频发问题,畅享游戏乐趣
    《原地起啡》是一款深受玩家喜爱的游戏,但在游戏中有时会遇到DLL文件丢失的问题,导致游戏无法正常启动或频繁崩溃。幸运的是,使用DirectX修复工具可以有效解决这一问题。以下是详细的步骤,帮助玩家快速修复DLL文件丢失的问题。1.下载DirectX修复工具:•访问官方网站或其他可信的......
  • 解决《浮岛物语》DLL错误频发,轻松畅玩游戏
    《浮岛物语》是一款深受玩家喜爱的冒险建造类游戏,但在游玩过程中,不少玩家遇到了DLL错误频发的问题,导致游戏无法正常启动或频繁崩溃。为了帮助大家顺利解决问题,以下是一些有效的处理方法,确保您能够畅享游戏的乐趣。1.验证游戏文件完整性:首先,通过Steam或其他游戏平台验证游......
  • 揭示Newman教授的错误:Dijkstra算法的松弛次序与最短路径中的边次序不一定相同
    揭示Newman教授的错误:Dijkstra算法的松弛次序与最短路径中的边次序不一定相同Dijkstra算法简介Newman教授的观点反驳观点示例图Dijkstra算法的执行过程分析松弛次序与最短路径中的边次序结论C语言实现Dijkstra算法在探讨Dijkstra算法的松弛次序是否一定与最......
  • 为何服务器会显示密码错误?
    服务器显示“密码错误”的原因可能有多种,以下是一些常见原因及相应的排查步骤,帮助你系统地解决问题:1. 确认输入信息首先,确保输入的用户名和密码完全正确。注意大小写敏感性,并检查是否有额外的空格或特殊字符。尝试使用其他已知正确的管理员账户登录,以排除输入错误的可能性。2.......
  • 网站后台显示登录密码错误怎么办?
    当网站后台显示登录密码错误时,可以按照以下逻辑步骤进行排查和处理:1. 确认输入信息首先,确保输入的用户名和密码完全正确。注意大小写敏感性,并检查是否有额外的空格或特殊字符。尝试使用其他已知正确的管理员账户登录,以排除输入错误的可能性。2. 清除浏览器缓存和Cookie有时......
  • 公司服务器密码设置错误,该如何快速解决?
    当公司服务器密码设置错误时,可以按照以下逻辑步骤快速解决:1. 确认当前问题首先,明确是哪个账户的密码设置错误(如SSH、数据库、控制面板等)。记录下具体的错误信息和登录界面提示,以便后续排查。2. 使用备用访问方式如果无法通过密码登录,尝试使用其他访问方式:SSH密钥对:如果有......