int func()
{
int bIsErrOccur = 0;
//do something that might invoke errors
if(bIsErrOccur) //Stage 1: error occurred
return -1; //Stage 2: generate error indicator
//...
return 0;
}
int main(void)
{
if(func() != 0) //Stage 3: detect error
{
//Stage 4: handle error
}
//Stage 5: recover or abort
return 0;
}
if((p = malloc(100)) == NULL)
//...
if((c = getchar()) == EOF)
//...
if((ticks = clock()) < 0)
//...
char *IntToAscii(int dwVal, char *pszRes, int dwRadix)
{
if(NULL == pszRes)
return "Arg2Null";
if((dwRadix < 2) || (dwRadix > 36))
return "Arg3OutOfRange";
//...
return pszRes;
}
typedef enum{
S_OK, //成功
S_ERROR, //失败(原因未明确),通用状态
S_NULL_POINTER, //入参指针为NULL
S_ILLEGAL_PARAM, //参数值非法,通用
S_OUT_OF_RANGE, //参数值越限
S_MAX_STATUS //不可作为返回值状态,仅作枚举最值使用
}FUNC_STATUS;
((eRetCode) == S_OK ? : \
((eRetCode) == S_ERROR ? : \
((eRetCode) == S_NULL_POINTER ? : \
((eRetCode) == S_ILLEGAL_PARAM ? : \
((eRetCode) == S_OUT_OF_RANGE ? : \
)))))
extern int errno;
extern int *__errno_location(void);
//调用库函数
if(返回错误值)
//检查errno
if (somecall() == -1)
{
printf("somecall() failed\n");
if(errno == ...) { ... }
}
if (somecall() == -1)
{
int dwErrSaved = errno;
printf("somecall() failed\n");
if(dwErrSaved == ...) { ... }
}
char *strerror(int errnum);
void perror(const char *msg);
int main(int argc, char** argv)
{
errno = 0;
FILE *pFile = fopen(argv[1], "r");
if(NULL == pFile)
{
printf("Cannot open file '%s'(%s)!\n", argv[1], strerror(errno));
perror("Open file failed");
}
else
{
printf("Open file '%s'(%s)!\n", argv[1], strerror(errno));
perror("Open file");
fclose(pFile);
}
return 0;
}
[wangxiaoyuan_@localhost test1]$ ./GlbErr /sdb1/wangxiaoyuan/linux_test/test1/test.c
Open file '/sdb1/wangxiaoyuan/linux_test/test1/test.c'(Success)!
Open file: Success
[wangxiaoyuan_@localhost test1]$ ./GlbErr NonexistentFile.h
Cannot open file 'NonexistentFile.h'(No such file or directory)!
Open file failed: No such file or directory
[wangxiaoyuan_@localhost test1]$ ./GlbErr NonexistentFile.h > test
Open file failed: No such file or directory
[wangxiaoyuan_@localhost test1]$ ./GlbErr NonexistentFile.h 2> test
Cannot open file 'NonexistentFile.h'(No such file or directory)!
int *_fpErrNo(void)
{
static int dwLocalErrNo = 0;
return &dwLocalErrNo;
}
//define other error macros...
int Callee(void)
{
ErrNo = 1;
return -1;
}
int main(void)
{
ErrNo = 0;
if((-1 == Callee()) && (EOUTOFRANGE == ErrNo))
printf("Callee failed(ErrNo:%d)!\n", ErrNo);
return 0;
}
double Division(double fDividend, double fDivisor)
{
return fDividend/fDivisor;
}
int main(void)
{
int dwFlag = 0;
if(1 == dwFlag)
{
RaiseException:
printf("The divisor cannot be 0!\n");
exit(1);
}
dwFlag = 1;
double fDividend = 0.0, fDivisor = 0.0;
printf("Enter the dividend: ");
scanf("%lf", &fDividend);
printf("Enter the divisor : ");
scanf("%lf", &fDivisor);
if(0 == fDivisor) //不太严谨的浮点数判0比较
goto RaiseException;
printf("The quotient is %.2lf\n", Division(fDividend, fDivisor));
return 0;
}
[ ]$ ./test
Enter the dividend: 10
Enter the divisor : 0
The divisor cannot be 0!
[ ]$ ./test
Enter the dividend: 10
Enter the divisor : 2
The quotient is 5.00
虽然goto语句会破坏代码结构性,但却非常适用于集中错误处理。伪代码示例如下:
CallerFunc()
{
if((ret = CalleeFunc1()) < 0);
goto ErrHandle;
if((ret = CalleeFunc2()) < 0);
goto ErrHandle;
if((ret = CalleeFunc3()) < 0);
goto ErrHandle;
//...
return;
ErrHandle:
//Handle Error(e.g. printf)
return;
}
int setjmp(jmp_buf env);
void longjmp(jmp_buf env,int val);
jmp_buf gJmpBuf;
void Func1(){
printf("Enter Func1\n");
if(0)longjmp(gJmpBuf, 1);
}
void Func2(){
printf("Enter Func2\n");
if(0)longjmp(gJmpBuf, 2);
}
void Func3(){
printf("Enter Func3\n");
if(1)longjmp(gJmpBuf, 3);
}
int main(void)
{
int dwJmpRet = setjmp(gJmpBuf);
printf("dwJmpRet = %d\n", dwJmpRet);
if(0 == dwJmpRet)
{
Func1();
Func2();
Func3();
}
else
{
switch(dwJmpRet)
{
case 1:
printf("Jump back from Func1\n");
break;
case 2:
printf("Jump back from Func2\n");
break;
case 3:
printf("Jump back from Func3\n");
break;
default:
printf("Unknown Func!\n");
break;
}
}
return 0;
}
dwJmpRet = 0
Enter Func1
Enter Func2
Enter Func3
dwJmpRet = 3
Jump back from Func3
jmp_buf gJmpBuf;
void RaiseException(void)
{
printf("Exception is raised: ");
longjmp(gJmpBuf, 1); //throw,跳转至异常处理代码
printf("This line should never get printed!\n");
}
double Division(double fDividend, double fDivisor)
{
return fDividend/fDivisor;
}
int main(void)
{
double fDividend = 0.0, fDivisor = 0.0;
printf("Enter the dividend: ");
scanf("%lf", &fDividend);
printf("Enter the divisor : ");
if(0 == setjmp(gJmpBuf)) //try块
{
scanf("%lf", &fDivisor);
if(0 == fDivisor) //也可将该判断及RaiseException置于Division内
RaiseException();
printf("The quotient is %.2lf\n", Division(fDividend, fDivisor));
}
else //catch块(异常处理代码)
{
printf("The divisor cannot be 0!\n");
}
return 0;
}
Enter the dividend: 10
Enter the divisor : 0
Exception is raised: The divisor cannot be 0!
typedef void (*fpSigFunc)(int);
fpSigFunc signal(int signo, fpSigFunc fpHandler);
int raise(int signo);
void fphandler(int dwSigNo)
{
printf("Exception is raised, dwSigNo=%d!\n", dwSigNo);
}
int main(void)
{
if(SIG_ERR == signal(SIGFPE, fphandler))
{
fprintf(stderr, "Fail to set SIGFPE handler!\n");
exit(EXIT_FAILURE);
}
double fDividend = 10.0, fDivisor = 0.0;
if(0 == fDivisor)
{
raise(SIGFPE);
exit(EXIT_FAILURE);
}
printf("The quotient is %.2lf\n", fDividend/fDivisor);
return 0;
}
int main(void)
{
if(SIG_ERR == signal(SIGFPE, fphandler))
{
fprintf(stderr, "Fail to set SIGFPE handler!\n");
exit(EXIT_FAILURE);
}
int dwDividend = 10, dwDivisor = 0;
double fQuotient = dwDividend/dwDivisor;
printf("The quotient is %.2lf\n", fQuotient);
return 0;
}
jmp_buf gJmpBuf;
void fphandler(int dwSigNo)
{
printf("Exception is raised, dwSigNo=%d!\n", dwSigNo);
longjmp(gJmpBuf, 1);
}
int main(void)
{
if(SIG_ERR == signal(SIGFPE, SIG_DFL))
{
fprintf(stderr, "Fail to set SIGFPE handler!\n");
exit(EXIT_FAILURE);
}
int dwDividend = 10, dwDivisor = 0;
if(0 == setjmp(gJmpBuf))
{
double fQuotient = dwDividend/dwDivisor;
printf("The quotient is %.2lf\n", fQuotient);
}
else
{
printf("The divisor cannot be 0!\n");
}
return 0;
}
void exit(int status);
void _Exit(int status);
void _exit(int status);
int main(void)
{
printf("Using exit...\n");
printf("This is the content in buffer");
exit(0);
printf("This line will never be reached\n");
}
Using exit...
This is the content in buffer(结尾无换行符)
int main(void)
{
printf("Using _exit...\n");
printf("This is the content in buffer");
fprintf(stdout, "Standard output stream");
fprintf(stderr, "Standard error stream");
//fflush(stdout);
_exit(0);
}
Using _exit...
Standard error stream(结尾无换行符)
Using _exit...
Standard error streamThis is the content in bufferStandard output stream(结尾无换行符)
int atexit(void (*func)(void));
double Division(double fDividend, double fDivisor)
{
return fDividend/fDivisor;
}
void RaiseException1(void)
{
printf("Exception is raised: \n");
}
void RaiseException2(void)
{
printf("The divisor cannot be 0!\n");
}
int main(void)
{
double fDividend = 0.0, fDivisor = 0.0;
printf("Enter the dividend: ");
scanf("%lf", &fDividend);
printf("Enter the divisor : ");
scanf("%lf", &fDivisor);
if(0 == fDivisor)
{
atexit(RaiseException2);
atexit(RaiseException1);
exit(EXIT_FAILURE);
}
printf("The quotient is %.2lf\n", Division(fDividend, fDivisor));
return 0;
}
Enter the dividend: 10
Enter the divisor : 0
Exception is raised:
The divisor cannot be 0!
#include <stdlib.h>
void abort(void);
void abort(void)
{
raise(SIGABRT);
exit(EXIT_FAILURE);
}
extern void __assert((const char *, const char *, int, const char *));
((void) ((expr) || \
(__assert(
void __assert(const char *assertion, const char * filename,
int linenumber, register const char * function)
{
fprintf(stderr, " [%s(%d)%s] Assertion '%s' failed.\n",
filename, linenumber,
((function == NULL) ? "UnknownFunc" : function),
assertion);
abort();
}
(fprintf(stderr, "[%s(%d)] Assertion '%s' failed.\n", \
__FILE__, __LINE__,
char *Strcpy(char *pszDst, const char *pszSrc)
{
char *pszDstOrig = pszDst;
assert((pszDst != NULL) && (pszSrc != NULL));
while((*pszDst++ = *pszSrc++) != '\0');
return pszDstOrig;
}
FILE *OpenFile(const char *pszName, const char *pszMode)
{
FILE *pFile = fopen(pszName, pszMode);
assert(pFile != NULL);
if(NULL == pFile)
return NULL;
//...
return pFile;
}
int main(void)
{
int dwChg = 0;
assert(dwChg = 1);
if(0 == dwChg)
printf("Assertion should be enabled!\n");
return 0;
}
pid_t Fork(void) //首字母大写,以区分系统函数fork()
{
pid_t pid;
if((pid = fork())<0)
{
fprintf(stderr, "Fork error: %s\n", strerror(errno));
exit(0);
}
return pid;
}
int daemon_proc; /* set nonzero by daemon_init() */
static void err_doit(int errnoflag, int level, const char * fmt, va_list ap)
{
int errno_save, n;
char buf[MAXLINE + 1];
errno_save = errno; /* Value caller might want printed. */
vsnprintf(buf, MAXLINE, fmt, ap);
vsprintf(buf, fmt, ap); /* This is not safe */
n = strlen(buf);
if (errnoflag) {
snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
}
strcat(buf, "\n");
if (daemon_proc) {
syslog(level, buf);
} else {
fflush(stdout); /* In case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
}
return;
}
void err_ret(const char * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, LOG_INFO, fmt, ap);
va_end(ap);
return;
}
作者:clover-toeic
原文:https://www.cnblogs.com/clover-toeic/p/3919857.html
飞机上一般是什么操作系统?
高速CAN、容错CAN、LIN总线有什么区别?
大佬终于把鸿蒙OS讲明白了,收藏了!