C/C++错误信息

C/C++错误信息

目录

1. errno 和 perror()

示例:

2. strerror()

示例:

3. perror() 和 strerror() 区别

4. exit() 和 abort()

示例:

示例:

5. assert()

示例:

6. setjmp() 和 longjmp()

示例:

7. strerror_r()

示例:

8. perror() 和 strerror() 适用场景

常见的 C/C++ 错误信息和函数

常见的错误信息

常见的函数

总结


在 C/C++ 编程中,错误信息的捕获和处理是保证程序健壮性的重要部分。错误通常通过函数的返回值或者全局变量 errno 来表示。为了方便调试和错误处理,C/C++ 提供了多种函数和方法来获取和输出错误信息。以下是 C/C++ 错误处理的常见方法及函数介绍:

1. errno 和 perror()

  • **errno**:errno 是一个全局变量,当系统调用或库函数失败时,它会被设置为一个错误代码。errno 是由操作系统在发生错误时设置的,每个错误代码代表特定类型的错误。
  • **perror()**:perror() 用于打印基于 errno 错误码的错误信息。它将 errno 的值转换为对应的错误消息并输出。如果提供了自定义的前缀字符串,则会一起输出。
示例:
#include <stdio.h> #include <errno.h> #include <string.h> int main() { FILE *file = fopen("non_existent_file.txt", "r"); if (!file) { perror("File opening failed"); } return 0; } 

输出:

File opening failed: No such file or directory 

在此例中,perror() 输出了一个由 errno 设置的错误信息,具体是“没有这样的文件或目录”。

2. strerror()

  • **strerror()**:strerror() 函数用于将 errno 错误代码转换为可读的字符串,返回与 errno 对应的错误消息的指针。可以在程序中直接调用它来获取详细的错误描述。
示例:
#include <stdio.h> #include <errno.h> #include <string.h> int main() { FILE *file = fopen("non_existent_file.txt", "r"); if (!file) { printf("Error: %s\n", strerror(errno)); } return 0; } 

输出:

Error: No such file or directory 

3. perror() 和 strerror() 区别

  • perror() 会自动将错误信息输出到标准错误流 stderr,并可以附带自定义的前缀。
  • strerror() 返回一个指向错误信息的指针,可以在程序中自己控制输出。

4. exit() 和 abort()

  • **exit()**:exit() 用于退出程序并返回一个指定的状态码。返回的状态码可以用来表示程序的执行状态,通常 0 表示成功,非零值表示错误。
示例:
#include <stdio.h> #include <stdlib.h> int main() { if (some_error_condition) { fprintf(stderr, "An error occurred\n"); exit(1); // Exit with status 1 (error) } return 0; } 
  • **abort()**:abort() 用于立即终止程序,通常在程序遇到无法恢复的错误时使用。调用 abort() 后,程序会立即中止,并且返回一个未定义的错误状态。
示例:
#include <stdlib.h> #include <stdio.h> int main() { if (some_fatal_error) { abort(); // Immediately terminate the program } return 0; } 

5. assert()

  • **assert()**:assert() 是用于调试时的一个宏,检查条件表达式是否为真。如果条件不为真,程序会输出错误信息并调用 abort() 终止程序。assert() 主要用于开发和调试阶段,不应该用于生产代码。
示例:
#include <assert.h> #include <stdio.h> int main() { int x = 5; assert(x == 10); // This will fail and abort the program return 0; } 

6. setjmp() 和 longjmp()

  • **setjmp()**:setjmp() 用于设置一个恢复点。如果程序在后续调用 longjmp() 时跳转到该恢复点,setjmp() 会返回一个非零值。
  • **longjmp()**:longjmp() 用于从 setjmp() 所在的地方跳转到程序的某个恢复点。它可以用于错误处理,但一般不推荐作为常规的错误处理机制。
示例:
#include <setjmp.h> #include <stdio.h> jmp_buf env; void error_recovery() { printf("Error occurred, recovering...\n"); longjmp(env, 1); // Jump back to setjmp } int main() { if (setjmp(env) != 0) { printf("Recovered from error\n"); return 0; } error_recovery(); // Call this to simulate error return 0; } 

7. strerror_r()

  • **strerror_r()**:strerror_r() 是线程安全的 strerror() 版本,它将错误信息写入传入的缓冲区中。由于 strerror() 不是线程安全的(它使用静态缓冲区),所以在多线程程序中推荐使用 strerror_r()
示例:
#include <stdio.h> #include <string.h> #include <errno.h> int main() { char buf[256]; errno = ENOENT; strerror_r(errno, buf, sizeof(buf)); printf("Error: %s\n", buf); return 0; } 

8. perror() 和 strerror() 适用场景

  • **perror()**:适用于错误发生时立即输出错误信息,通常与文件操作、系统调用等直接相关的错误。
  • **strerror()**:适用于在多个地方需要引用或自定义错误消息输出的场景,尤其在日志记录和调试时很有用。

常见的 C/C++ 错误信息和函数

常见的错误信息
  • **ENOMEM**:内存不足
  • **EAGAIN**:暂时不可用,通常表示资源忙或阻塞
  • **EINVAL**:无效参数
  • **EBADF**:无效的文件描述符
  • **EIO**:输入/输出错误
  • **EPERM**:操作不允许
  • **ENOENT**:没有文件或目录
常见的函数
  • **fopen()open()**:文件打开错误,返回 NULL 或 -1,需要使用 errno 判断具体错误。
  • **socket()**:创建套接字时的错误。
  • **connect()send()recv()**:网络编程中的错误。

总结

C/C++ 提供了一系列强大的错误处理机制,包括全局变量 errno 和函数 perror()strerror() 等来输出和捕获错误信息。通过合理地使用这些函数,可以有效地捕获并报告程序中的错误,帮助开发人员在调试和生产环境中定位问题。

Read more

手写一个C++ TCP服务器实现自定义协议(顺便解决粘包问题)

手写一个C++ TCP服务器实现自定义协议(顺便解决粘包问题)

在之前的博客中,我们了解了关于UDP和TCP的网络编程,直观的感受了一下网络套接字是如何使用的,并且成功的完成了客户端与服务端的网络通信,但是其中还有一个小细节我们可能会忽略,就是UDP是基于数据报进行传输的,一下子就将所有我们要发送的信息传送给对方,但是我们的TCP可是基于字节流进行传输的,我们如何保证读取上来的数据,是一个完整的报文呢? 我们在进行TCP网络通信的时候,通过调用connec函数调用,使客户端可以和服务端保持链接之后,客户端将自己想要发送的数据通过write系统调用写进对应的socket函数调用给我们返回的文件描述符所对应的文件中。 现在有一个问题就是我们向文件中写入的时候,直接将其放入即可,但是想要往出拿的时候就有点困难了,想要往出拿的人如果不知道放的人是如何放的,就会造成一系列的错误,这就好比放数据时先放了一个整形,又放了一个浮点数,还放了一个字符串,然而拿的人按照字符串,整形,浮点数这样的方式进行获取,这就会导致数据不一致的现象,所以一旦我们要发送一些带有结构化的数据时,就必须再次制定——协议,这样才能满足我们想要返送一些结构化数据的需求。 TCP是传输控

By Ne0inhk
千面之法: 释放 C++ 多态的灵活威力

千面之法: 释放 C++ 多态的灵活威力

目录 1:多态的概念 1.1:概念 2.多态的定义与实现 2.1:多态的构成条件 2.2:虚函数 2.3:虚函数的重写 2.3.1:虚函数重写的两个例外 2.3.1.1:协变(基类与派生类函数的返回值不同,基类虚函数返回基类对象的指针或引用,派生类虚函数返回派生类对象的指针或引用时) 2.3.1.2:析构函数的重写 2.4:C++11 override和final 2.4.1:final关键字 2.4.2:override关键字 2.5:重载、

By Ne0inhk
蓝桥杯手把手教你备战(C/C++ B组)(最全面!最贴心!适合小白!)

蓝桥杯手把手教你备战(C/C++ B组)(最全面!最贴心!适合小白!)

比赛环境:网盘资源分享 通过网盘分享的文件:蓝桥杯比赛环境 链接: https://pan.baidu.com/s/1eh85AW-y83ibCmEo8ByBwA?pwd=1234 提取码: 1234 1 常见问题答疑 1.1 蓝桥杯含金量高不高? 说起蓝桥杯,不得不提ACM。 ACM是国际大学生程序设计竞赛(ACM-ICPC),被誉为计算机领域的“奥运会”,是世界上,规模最大、水平最高、最具影响力的国际大学生程序设计竞赛。 ACM难度较高,当然含金量也更高, 那么蓝桥杯的含金量肯定比不过ACM,但是其具有独特的优势。 蓝桥杯难度更低,更易拿奖,同时在计算机行业具有较高认可度。 ACM适合那些智商高或者编程经验丰富(学习算法1年以上)的选手参赛。而蓝桥杯适合小白,适合期望快速获得编程领域一个认可证书而没有太多时间投入的参赛者。 1.2 获奖到底难不难? 蓝桥杯分为省赛和国赛。 省赛时: 与你竞争的是同省的人,所以获奖难度与你所在的省份有一定关系。 强省(

By Ne0inhk
深入解析C++驱动开发实战:优化高效稳定的驱动应用

深入解析C++驱动开发实战:优化高效稳定的驱动应用

深入解析C++驱动开发实战:优化高效稳定的驱动应用 在现代计算机系统中,驱动程序(Driver)扮演着至关重要的角色,作为操作系统与硬件设备之间的桥梁,驱动程序负责管理和控制硬件资源,确保系统的稳定与高效运行。随着设备复杂度的增加和系统性能需求的提升,如何使用C++高效、稳定地开发驱动程序,成为开发者亟需解决的关键问题。本文将深入探讨C++驱动开发中的常见问题及其优化策略,通过详细的示例代码,帮助开发者构建高性能、稳定可靠的驱动应用。 🧑 博主简介:ZEEKLOG博客专家、ZEEKLOG平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用,熟悉DICOM医学影像及DICOM协议,业余时间自学JavaScript,Vue,qt,python等,具备多种混合语言开发能力。撰写博客分享知识,致力于帮助编程爱好者共同进步。欢迎关注、交流及合作,

By Ne0inhk