【C语言】异常处理 | assert函数 | errno错误码

C语言传统的处理错误的方式

C语言传统的处理错误的方式主要包括assert终止程序返回或设置错误码两种方式。

1. 终止程序(例如使用 assert

#include <stdio.h>
#include <assert.h>

void divide(int a, int b) 
{
   
    assert(b != 0);  // 防止除0错误:如果b为0,则终止程序
    int result = a / b;
    printf("Result: %d\n", result);
}

int main() 
{
   
    divide(10, 2);    // 正常情况
    divide(5, 0);     // 会终止程序,因为除数为0
    return 0;
}

请添加图片描述

上述代码中,divide 函数使用 assert 来确保除数不为0,如果除数为0,则终止程序。这种方式的缺陷在于终止程序对用户来说不够友好,且难以接受。

2. 返回/设置错误码

手动实现
#include <stdio.h>
#include <stdlib.h>

int divide(int a, int b, int* result) 
{
   
    if (b == 0) 
    {
   
        return -1;  // 返回错误码表示除数为0
    }
    *result = a / b;
    return 0;       // 返回0表示成功
}

int main() 
{
   
    int result;
    int status;

    status = divide(10, 2, &result);
    if (status == 0) 
    {
   
        printf("Result: %d\n", result);
    }
    else 
    {
   
        printf("Error: Division by zero\n");
    }

    status = divide(5, 0, &result);
    if (status == 0) 
    {
   
        printf("Result: %d\n", result);
    }
    else 
    {
   
        printf("Error: Division by zero\n");
    }

    return 0;
}

上述代码中,divide 函数返回一个整数作为状态码,如果除数为0,则返回-1表示错误,否则返回0表示成功。在 main 函数中,根据返回的状态码来判断是否出现错误,并进行相应的处理。这种方式的缺陷在于程序员需要手动检查错误码,并进行处理,不够直观。


当然,如Linux系统的很多库的接口函数、C语言的标准库都是通过把错误码放到errno中,表示错误。
而且,Linux系统调用和C标准库中的errno使用的是几乎同一套错误码
请添加图片描述

C语言库函数内置的错误码

使用C语言的标准库的库函数时,这些函数通常会将发生的错误码存储在全局变量errno中。errno是一个整数,在<errno.h>头文件中定义了一系列常量,每个常量代表一个可能的错误码。

程序员可以使用strerror函数获取与特定错误码相对应的错误字符串,然后将其打印出来。下面是一个简单的示例:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main() 
{
   
    FILE *file = fopen("nonexistent_file.txt", "r");
    
    if (file == NULL) 
    {
   
        perror("打开文件时发生错误");
        printf("错误码:%d,错误信息:%s\n", errno, strerror(errno));
    } else 
    {
   
        // 文件打开成功,进行相应的操作
        fclose(file);
    }

    return 0;
}

请添加图片描述

在这个例子中,如果fopen打开文件失败,perror函数将打印与当前errno值相对应的错误信息(中文提示),而strerror函数用于获取错误字符串,然后将其打印出来。这有助于程序员更容易理解和处理发生的错误。

Linux系统调用内置的错误码

当在Linux(例如CentOS 7)下使用系统调用或库函数时,errno的使用方式是相似的。以下是一个使用系统调用open的例子,演示如何检查错误并打印相关信息:

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

int main() {
   
    int fd = open("nonexistent_file.txt", O_RDONLY);

    if (fd == -1) {
   
        perror("打开文件时发生错误");
        printf("错误码:%d,错误信息:%s\n", errno, strerror(errno));
    } else {
   
        // 文件打开成功,进行相应的操作
        close(fd);
    }

    return 0;
}

请添加图片描述

在这个例子中,open系统调用尝试打开一个不存在的文件。如果调用失败,perror函数将打印中文错误信息,strerror函数将打印与errno值相对应的英文错误字符串。程序员可以根据错误信息更好地了解发生的问题,并根据需要采取适当的处理措施。

总结一下:
实际中,C语言通常结合使用 assert断言设置错误码 这两种方式:

  • 对于非常严重的错误,例如内存错误,除0错误等,会选择终止程序。
  • 对于一些可以预见的错误,会使用返回错误码的方式进行处理,方便程序员根据需要进行错误处理。

相关推荐

  1. C语言——assert函数

    2024-02-03 09:16:03       62 阅读
  2. python异常assert语句

    2024-02-03 09:16:03       74 阅读
  3. C#中错误异常处理

    2024-02-03 09:16:03       26 阅读
  4. C语言大师(8)异常处理

    2024-02-03 09:16:03       47 阅读
  5. C语言stderr、errno、strerror、perror

    2024-02-03 09:16:03       49 阅读
  6. 二、C#基础语法异常处理

    2024-02-03 09:16:03       50 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-03 09:16:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-03 09:16:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-03 09:16:03       82 阅读
  4. Python语言-面向对象

    2024-02-03 09:16:03       91 阅读

热门阅读

  1. 【Redis】理论基础 - 持久化

    2024-02-03 09:16:03       47 阅读
  2. 8-Docker网路模式之自定义网络

    2024-02-03 09:16:03       60 阅读
  3. curl之网络接口

    2024-02-03 09:16:03       61 阅读
  4. Spring MVC 框架无法找到合适的消息转换器

    2024-02-03 09:16:03       46 阅读
  5. CSS 选择器与相关规则详解

    2024-02-03 09:16:03       54 阅读
  6. JeecgBoot 3.6.1 vue页面定时刷新列表

    2024-02-03 09:16:03       53 阅读