exit vs return
Từ trước đến nay tôi vẫn sử dụng hai hàm exit và return một cách khá “vô tư”, coi như đó đơn thuần là 2 lệnh cần thiết đặt ở dòng cuối cùng của hàm main trong chương trình C (đối với hàm exit) và chương trình C++ (đối với hàm return) mà không thực sự hiểu ý nghĩa của chúng. Cho đến một ngày, tôi gặp phải một tình huống khá rắc rối: Một chương trình C++ đơn giản, cú pháp hoàn toàn đúng nhưng luôn bị lỗi core dumped sau khi chạy qua lệnh return của hàm main. Sau một thời gian đánh vật với chương trình này mà không có hiệu quả, tôi chợt nảy ra ý định tại sao không sử dụng hàm exit thay cho return nhỉ? Kết quả thật bất ngờ: Sau khi thay hàm return bằng exit, lỗi core dumped đã biến mất!!! Vậy phải chăng exit tốt hơn return?
Sau một hồi mò mẫm trên Google, tôi đã thu được một số thông tin sau đây (trích từ trang http://www.velocityreviews.com/forums/t285499-return-vs-exit.html)
- “Hàm exit chẳng có gì là bí hiểm cả. Đó là một hàm của C và do vậy không biết đến một số yếu tố của C++, ví dụ các hàm destructor. Bởi vậy khi kết thúc hàm main các destructor sẽ không được gọi.”
- “exit() là một hàm không bao giờ “trả về”. Vì vậy khi sử dụng exit ở cuối hàm main thì hàm main sẽ không bao giờ đạt tới điểm kết thúc. Kết quả là stack sẽ không được giải phóng và các destructor sẽ không được gọi. Nghĩa là đoạn mã gây ra lỗi core dumped sẽ không được gọi”
Chúng ta có thể kiểm chứng điều này bằng chương trình sau đây:
#include< iostream >
#include< cstdlib > class MyClass
{
public:
~MyClass() {
std::cout << "The destructor is called" << std::endl;
}
};
int main()
{
MyClass c;
std::cout << "In the main function" << std::endl;
return EXIT_SUCCESS;
}
Dịch và chạy chương trình trên chúng ta thu được kết quả như sau:
In the main function
The destructor is called
Tuy nhiên nếu thay thế return bằng hàm exit như sau:
exit( EXIT_SUCCESS );
Kết quả chạy chương trình là:
In the main function
Tóm lại, hàm exit() không giải quyết được lỗi core dumped của tôi mà chỉ “ẩn” lỗi này đi mà thôi. Bạn không nên sử dụng exit() ở cuối hàm main của các chương trình C++ vì như vậy dễ gây ra memory leak.
Trong trang web nói trên có đường link đến một trang khác phân tích về sự khác nhau giữa return, exit và abort
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
Tôi cũng đã viết mail hỏi anh Hoàng Trần (như thường lệ
) và nhận được email trả lời như sau:
“It is always good to use return and only use exit when your program need to be terminated immediately. Using return make your program’s logic clear, and sometimes it avoid memory leak or possible corruptions somewhere. In your case I guess might be your program has been corrupted memory and can not return (can release stack or something … ), but using exit make your program terminated. You see the result (output file) and think it’s good but actually you did not exit in correct way”
Một điều bổ ích nữa mà tôi học được từ email của anh là chúng ta nên sử dụng các constant EXIT_FAILURE và EXIT_SUCCESS để đảm bảo tính khả chuyển của chương trình. Tức là sử dụng:
return EXIT_SUCCESS thay cho return 0
return EXIT_FAILURE thay cho return 1
Tôi không biết thông tin lấy từ các trang web nói trên có đáng tin cậy hay không (vì tôi vốn chỉ tin vào các cuốn sách kinh điển), tuy nhiên ít nhất thì tôi cũng biết được rằng lỗi core dumped trong chương trình của tôi vẫn….chưa thể được giải quyết
( Đối với những lỗi core dumped xảy ra trong quá trình giải phóng bộ nhớ tôi vẫn không biết có phương pháp nào để giải quyết hay không. Có lẽ đây cũng là một chủ đề hay ho cần phải nghiên cứu.
Sự khác nhau giữa hai hàm exit và return có lẽ là khá hiển nhiên đối với nhiều người (tất nhiên trong đó không có tôi). Tuy nhiên, tôi đã rút ra được bài học rằng có nhiều điều tưởng như rất đơn giản nhưng khi dành thời gian tìm hiểu ta lại phát hiện ra rất nhiều điều thú vị về chúng. Trong C và C++ chắc chắn còn nhiều điều thú vị như vậy mà tôi chưa được biết.
leave a comment