Error handling

What is Error handling?

Error handing คือ การจัดการข้อผิดพลาด ซึ่งเป็นความผิดพลาดที่โดยทั่วไปแล้วไม่สามารถจัดการภายในโปรแกรม เมื่อเกิด Error ขึ้นอาจส่งผลให้การทำงานของโปรแกรมล้มเหลว เช่น หน่วยความจำไม่พอ เวอร์ชันการทำงานของ library ไม่ถูกรองรับ การเปิดไฟล์ที่ไม่มีอยู่จริง เป็นต้น จึงต้องมีการเขียน Error handling เพื่อแสดงสาเหตุของข้อผิดพลาดนั้นและทำให้โปรแกรมสามารถทำงานต่อไปได้

Different methods of Error handling

การเขียนโปรแกรมภาษา C ไม่ได้มีการสนับสนุนการจัดการข้อผิดพลาด (Error handling) โดยตรง ผู้ออกแบบโปรแกรมต้องทำการเขียนขึ้นมาเอง โดยการใช้คำสั่ง return ส่งคืนค่า -1 หรือ NULL ในกรณีที่เกิดข้อผิดพลาด และสามารถเขียน Error handling ด้วยการใช้ 'คำสั่ง if' ดังตัวอย่าง การหารด้วย 0 (Divide by Zero Errors) ดังต่อไปนี้

สำหรับภาษา C++ จะมีตัวสนับสนุนการจัดการข้อผิดพลาด เรียกว่า Exceptions handling ถึงแม้ว่าจะมีตัวสนับสนุนจัดการข้อผิดพลาด แต่ก็สามารถเขียน Error handling ได้เหมือนภาษา c

// err_p1_1.c
#include <stdio.h> 

int solution(int a,int b)
{
    if (b > 0) { 
    
        return a / b; 
    } 

    return -1;
}   

int main() {
    printf("%d\n",solution(102,0));
    printf("%d\n",solution(955,5));
    printf("%d\n",solution(1650,2));     
    return 0;
}
-1
191
825

อย่างที่รู้กันว่าโปรแกรมคอมพิวเตอร์จะไม่สามารถคำนวณค่าที่เกิดจากการหารด้วย 0 เนื่องจากจะส่งผลให้เกิดข้อผิดพลาดในการทำงานและไม่สามารถทำงานต่อไปได้ แต่จากตัวอย่างจะเห็นได้ว่าโปรแกรมสามารถทำงานต่อไปได้ด้วยการเขียน Error handling return ค่า -1

ข้อเสียของการส่งค่า return คือ จะทำให้คนอื่นนอกจากผู้ออกแบบโปรแกรมไม่ทราบว่าค่า -1 ที่ถูก return กลับมานั้นเกิดจากสาเหตุอะไร จึงได้มีการตั้งค่ารหัสตัวแปรส่วนกลาง (Global Variable) เพื่อระบุว่ารหัสตัวแปรที่ปรากฏเกิดจากสาเหตุอะไร ซึ่งสามารถค้นหารหัสตัวแปรข้อผิดพลาดต่าง ๆ ที่กำหนดไว้จาก <errno.h> ที่เป็น header file เรียกวิธีนี้ว่า Global Variable errno

Global Variable errno

Global Variable errno ถูกตั้งค่าเป็นตัวแปรส่วนกลางและระบุว่ามีข้อผิดพลาดอะไรที่เกิดขึ้นระหว่างการเรียกใช้ฟังก์ชันใด ๆ ซึ่งสามารถค้นหารหัสตัวแปรข้อผิดพลาดที่กำหนดไว้จาก <errno.h> (ภาษา C++ สามารถเรียกใช้ได้ทั้งแบบ <errno.h> และแบบ <cerrno>) ดังนั้นโปรแกรมเมอร์สามารถตรวจสอบค่าที่ส่งคืนและสามารถดำเนินการที่เหมาะสมโดยขึ้นอยู่กับค่าที่ส่งคืน ดังตารางต่อไปนี้

errno value จะไม่มีเลข 0 เนื่องจากเลข 0 หมายถึงไม่มีข้อผิดพลาดในโปรแกรม

// err_p1_3.c
#include <stdio.h> 
#include <errno.h> 
  
int main() 
{ 
    // If a file is opened which does not exist, 
    // then it will be an error and corresponding 
    // errno value will be set 
    FILE * fp; 
  
    // opening a file which does 
    // not exist. 
    fp = fopen("text.txt", "r"); 
  
    printf(" Value of errno: %d\n ", errno); 
  
    return 0; 
} 
Value of errno: 2

จากตัวอย่างจะเห็นว่าค่าตัวแปร errno ที่ถูกส่งออกมา คือ 2 หมายความว่า โปรแกรมไม่สามารถเปิดไฟล์ที่ต้องการ เนื่องจากไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว

ข้อเสียของการให้ส่งค่าตัวแปรแสดงข้อผิดพลาดเพียงอย่างเดียว คือจะทำให้เกิดความยุ่งยากในการหาคำอธิบายข้อผิดพลาด ดังนั้นจึงได้มีฟังก์ชัน perror() และ strerror() เข้ามาช่วยในการแสดงข้อผิดพลาด

คำถาม คำสั่ง FILE *fp และ fopen คืออะไร

คำตอบ เป็นรูปแบบการประกาศแฟ้มข้อมูลและเปิดแฟ้มข้อมูล

ข้อมูลอ่านเพิ่มเติม :: พื้นฐานการทำงานของไฟล์

perror() and strerror()

  • perror() ย่อมาจาก print error เป็นฟังก์ชันที่ใช้ในการแสดงข้อความของค่า errno ปัจจุบัน โดยที่สามารถแสดงข้อความที่กำหนดไว้ ก่อนการแสดงข้อผิดพลาด

void perror (char*msg);
  msg คือ ข้อความแบบกำหนดเองก่อนการแสดงข้อผิดพลาด
// err_p1_5.c
// C program to illustrate the 
// use of perror() 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
  
// Driver Code 
int main() 
{ 
    FILE* fp; 
  
    // Now try to open same file 
    fp = fopen("file.txt", "r"); 
  
    if (fp == NULL) { 
  
        perror("Error: "); 
        return (-1); 
    } 
  
    // Close the file pointer 
    fclose(fp); 
  
    return (0); 
}
Error: : No such file or directory

  • strerror() คือ ฟังก์ชันที่ใช้รับค่าตัวแปรของ errno เพื่อ return ข้อมูลประเภท string มาแสดงผลข้อผิดพลาด

// err_p1_7.c
// C program to illustrate the 
// use of strerror() 
#include <errno.h> 
#include <stdio.h> 
#include <string.h> 
  
// Driver Code 
int main() 
{ 
    FILE* fp; 
  
    fp = fopen("file.txt", "r"); 
  
    if (fp == NULL) { 
  
        printf("Value of errno: %d\n ", errno); 
        printf("The error message is : %s\n",strerror(errno)); 
        return (-1); 
    } 
  
    // Close the file pointer 
    fclose(fp); 
  
    return (0); 
}
Value of errno: 2
The error message is : No such file or directory

นอกจากนี้ยังมีฟังก์ชัน ferror() และ clearerr() ที่ใช้ในการตรวจจับข้อผิดพลาดในการ stream

ศึกษาเพิ่มเติม :: Error handling during file operations in C/C++

Exit Status

Exit Status จะต่างจาก errno, perror() และ strerror() ที่เป็นการแสดงผลข้อผิดพลาด เพื่อให้โปรแกรมสามารถทำงานต่อไปได้ แต่ Exit Status เป็นคำสั่งที่ใช้ในการออกจากโปรแกรม แบ่งออกเป็น 2 ประเภท คือ Exit Success และ Exit Failure ซึ่งต้องทำการ include ก่อน จึงจะสามารถใช้คำสั่ง exit()

1. Exit Success คือ การออกจากโปแกรมที่ไม่เกิดข้อผิดพลาด สามารถเลือกใช้ได้ 2 แบบ ดังต่อไปนี้

exit(EXIT_SUCCESS)
exit(0)

สร้างไฟล์ file.txt ก่อน run code ดังต่อไปนี้

// err_p2_1.c
#include <stdio.h> 
#include <stdio.h> 
  
int main() 
{ 
    FILE* file; 
  
    // opening the file in read-only mode 
    file = fopen("file.txt", "r"); 
  
    printf("File opening successful!"); 
  
    // EXIT_SUCCESS 
    exit(0); 
}
File opening successful!

2. Exit Failure คือ การออกจากโปรแกรมที่เกิดข้อผิดพลาด สามารถเลือกใช้ได้ 2 แบบ ดังต่อไปนี้

exit(EXIT_FAILURE)
exit(1)
// err_p2_3.c
#include <stdio.h> 
#include <stdlib.h>
  
int main() 
{ 
    FILE* file; 
  
    // open the file in read-only mode 
    file = fopen("myFile.txt", "r"); 
  
    if (file == NULL) { 
        printf("Error in opening file\n"); 
  
        // EXIT_FAILURE 
        exit(1); 
    } 
  
    // EXIT_SUCCESS 
    exit(0); 
} 

สำหรับ exit(EXIT_FAILURE) สามารถใช้จำนวนเต็มอื่นที่ไม่ใช่ 1 เพื่อระบุข้อผิดพลาดประเภทต่างๆ

แหล่งอ้างอิง ::

Last updated

Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University