====== تابع ()perror ======
اکثر توابع Network API هنگامی که با خطایی مواجه می شوند، یک متغییر global به نام errno را مقدار دهی میکنند که این متغییر توسط [[perror]] به error message های قابل نمایش تبدیل میشود:
#include
#include
void perror(const char *s);
این تابع ابتدا رشته s و سپس پیغام مربوط به آخرین خطای رخ داده را نمایش میدهد.
در عمل چون تعداد فراخوانی های [[perror]] زیاد است، برای فراخوانی آن از یک تکنیک بسیار جالب استفاده می شود. ابتدا یک ماکرو به شکل زیر تعریف شده :
// man 2 bind
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
و سپس در برنامه با این شکل استفاده می شود :
if (sockfd == -1)
handle_error("socket");
برای توضیح وجود do{....}while(0) در ماکرو باید گفت که این تکنیک کمک میکند این ماکرو در شرایط مختلف قابل استفاده و درست باشد. در مثال زیر :
#include
#include
#include
#include
#include
#include
#include
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while(0)
int main()
{
int sockfd;
sockfd = socket(0, 0, 0);
if (sockfd == -1)
handle_error("socket");
else
printf("I got a socket\n");
return 0;
}
اگر ماکرو به این شکل تعریف شود :
#define handle_error(msg) \
perror(msg); exit(EXIT_FAILURE);
کد توسط preprocessor به این شکل تبدیل شده و به دلیل فاصله بین if و else ترجمه نخواهد شد :
if (sockfd == -1)
perror(msg); exit(EXIT_FAILURE);
else
printf("I got a socket\n");
حتی اگر از { } کمک بگیریم و به این شکل ماکرو را تعریف کنیم :
#define handle_error(msg) \
{ perror(msg); exit(EXIT_FAILURE); }
این بار کد توسط preprocessor به شکل زیر تبدیل شده و بخاطر ; بعد از { باز هم بین if و else فاصله ایجاد شده و ترجمه نخواهد شد :
if (sockfd == -1)
{ perror(msg); exit(EXIT_FAILURE); };
else
printf("I got a socket\n");
غیر از روش do{....}while(0) با کمک if(1){....}else و با کمک comma operator هم می توان این مشکل را حل کرد. البته comma operator بسیار محدود است و در موقعیتهای ساده کار آمد خواهد بود :
#define handle_error(msg) \
if(1) { perror(msg); exit(EXIT_FAILURE); } else
#define handle_error(msg) \
perror(msg), exit(EXIT_FAILURE)
برای بررسی خروجی preprocessor می توان از E- در gcc استفاده کرد :
gcc -E file.c