ǰÑÔ
±¾ÎÄÖ÷Òª×ܽáǶÈëʽϵͳCÓïÑÔ±à³ÌÖУ¬Ö÷ÒªµÄ´íÎó´¦Àí·½Ê½¡£ÎÄÖÐÉæ¼°µÄ´úÂëÔËÐл·¾³ÈçÏ£º
Ò» ´íÎó¸ÅÄî
1.1 ´íÎó·ÖÀà
´ÓÑÏÖØÐÔ¶øÑÔ£¬³ÌÐò´íÎó¿É·ÖΪÖÂÃüÐԺͷÇÖÂÃüÐÔÁ½Àà¡£¶ÔÓÚÖÂÃüÐÔ´íÎó£¬ÎÞ·¨Ö´Ðлָ´¶¯×÷£¬×î¶àÖ»ÄÜÔÚÓû§ÆÁÄ»ÉÏ´òÓ¡³ö´íÏûÏ¢»ò½«ÆäдÈëÈÕÖ¾Îļþ£¬È»ºóÖÕÖ¹³ÌÐò£»¶ø¶ÔÓÚ·ÇÖÂÃüÐÔ´íÎ󣬶àÊý±¾ÖÊÉÏÊÇÔÝʱµÄ(Èç×ÊÔ´¶Ìȱ)£¬Ò»°ã»Ö¸´¶¯×÷ÊÇÑÓ³ÙһЩʱ¼äºóÔٴγ¢ÊÔ¡£
´Ó½»»¥ÐÔ¶øÑÔ£¬³ÌÐò´íÎó¿É·ÖΪÓû§´íÎóºÍÄÚ²¿´íÎóÁ½Àà¡£Óû§´íÎó³ÊÏÖ¸øÓû§£¬Í¨³£Ö¸Ã÷Óû§²Ù×÷ÉϵĴíÎó£»¶ø³ÌÐòÄÚ²¿´íÎó³ÊÏÖ¸ø³ÌÐòÔ±(¿ÉÄÜЯ´øÓû§²»¿É½Ó´¥µÄÊý¾Ýϸ½Ú)£¬ÓÃÓÚ²é´íºÍÅÅÕÏ¡£
Ó¦ÓóÌÐò¿ª·¢Õ߿ɾö¶¨»Ö¸´ÄÄЩ´íÎóÒÔ¼°ÈçºÎ»Ö¸´¡£ÀýÈ磬Èô´ÅÅÌÒÑÂú£¬¿É¿¼ÂÇɾ³ý·Ç±ØÐè»òÒѹýÆÚµÄÊý¾Ý£»ÈôÍøÂçÁ¬½Óʧ°Ü£¬¿É¿¼ÂǶÌʱ¼äÑÓ³ÙºóÖØ½¨Á¬½Ó¡£Ñ¡ÔñºÏÀíµÄ´íÎó»Ö¸´²ßÂÔ£¬¿É±ÜÃâÓ¦ÓóÌÐòµÄÒì³£ÖÕÖ¹£¬´Ó¶ø¸ÄÉÆÆä½¡×³ÐÔ¡£
1.2 ´¦Àí²½Öè
´íÎó´¦Àí¼´´¦Àí³ÌÐòÔËÐÐʱ³öÏÖµÄÈκÎÒâÍâ»òÒì³£Çé¿ö¡£µäÐ͵ĴíÎó´¦Àí°üº¬Îå¸ö²½Ö裺
1) ³ÌÐòÖ´ÐÐʱ·¢ÉúÈí¼þ´íÎ󡣸ôíÎó¿ÉÄܲúÉúÓÚ±»µ×²ãÇý¶¯»òÄÚºËÓ³ÉäΪÈí¼þ´íÎóµÄÓ²¼þÏìӦʼþ(Èç³ýÁã)¡£
2) ÒÔÒ»¸ö´íÎóָʾ·û(ÈçÕûÊý»ò½á¹¹Ìå)¼Ç¼´íÎóµÄÔÒò¼°Ïà¹ØÐÅÏ¢¡£
3) ³ÌÐò¼ì²â¸Ã´íÎó(¶ÁÈ¡´íÎóָʾ·û£¬»òÓÉÆäÖ÷¶¯Éϱ¨£©£»
4) ³ÌÐò¾ö¶¨ÈçºÎ´¦Àí´íÎó(ºöÂÔ¡¢²¿·Ö´¦Àí»òÍêÈ«´¦Àí)£»
5) »Ö¸´»òÖÕÖ¹³ÌÐòµÄÖ´ÐС£
ÉÏÊö²½ÖèÓÃCÓïÑÔ´úÂë±íÊöÈçÏ£º
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; } |
µ÷ÓÃÕß¿ÉÄÜÏ£Íûº¯Êý·µ»Ø³É¹¦Ê±±íʾÍêÈ«³É¹¦£¬Ê§°Üʱ³ÌÐò»Ö¸´µ½µ÷ÓÃǰµÄ״̬(µ«±»µ÷º¯ÊýºÜÄѱ£Ö¤Õâµã)¡£
¶þ ´íÎó´«µÝ
2.1 ·µ»ØÖµºÍ»Ø´«²ÎÊý
CÓïÑÔͨ³£Ê¹Ó÷µ»ØÖµÀ´±êÖ¾º¯ÊýÊÇ·ñÖ´Ðгɹ¦£¬µ÷ÓÃÕßͨ¹ýifµÈÓï¾ä¼ì²é¸Ã·µ»ØÖµÒÔÅжϺ¯ÊýÖ´ÐÐÇé¿ö¡£³£¼ûµÄ¼¸ÖÖµ÷ÓÃÐÎʽÈçÏ£º
if((p = malloc(100)) == NULL) //... if((c = getchar()) == EOF) //... if((ticks = clock()) < 0) //... |
Unixϵͳµ÷Óü¶º¯Êý(ºÍһЩÀϵÄPosixº¯Êý)µÄ·µ»ØÖµÓÐʱ¼È°üÀ¨´íÎó´úÂëÒ²°üÀ¨ÓÐÓýá¹û¡£Òò´Ë£¬ÉÏÊöµ÷ÓÃÐÎʽ¿ÉÔÚͬһÌõÓï¾äÖнÓÊÕ·µ»ØÖµ²¢¼ì²é´íÎó(µ±Ö´Ðгɹ¦Ê±·µ»ØºÏ·¨µÄÊý¾ÝÖµ)¡£
·µ»ØÖµ·½Ê½µÄºÃ´¦ÊǼò±ãºÍ¸ßЧ£¬µ«ÈÔ´æÔڽ϶àÎÊÌ⣺
1) ´úÂë¿É¶ÁÐÔ½µµÍ
ûÓзµ»ØÖµµÄº¯ÊýÊDz»¿É¿¿µÄ¡£µ«Èôÿ¸öº¯Êý¶¼¾ßÓзµ»ØÖµ£¬Îª±£³Ö³ÌÐò½¡×³ÐÔ£¬¾Í±ØÐë¶Ôÿ¸öº¯Êý½øÐÐÕýÈ·ÐÔÑéÖ¤£¬¼´µ÷ÓÃʱ¼ì²éÆä·µ»ØÖµ¡£ÕâÑù£¬´úÂëÖкܴóÒ»²¿·Ö¿ÉÄÜ»¨·ÑÔÚ´íÎó´¦ÀíÉÏ£¬ÇÒÅÅ´í´úÂëºÍÕý³£Á÷³Ì´úÂë½ÁÔÚÒ»Æð£¬±È½Ï»ìÂÒ¡£
2) ÖÊÁ¿½µ¼¶
Ìõ¼þÓï¾äÏà±ÈÆäËûÀàÐ͵ÄÓï¾äDZ²Ø¸ü¶àµÄ´íÎó¡£²»±ØÒªµÄÌõ¼þÓï¾ä»áÔö¼ÓÅÅÕϺͰ׺вâÊԵŤ×÷Á¿¡£
3) ÐÅÏ¢ÓÐÏÞ
ͨ¹ý·µ»ØÖµÖ»ÄÜ·µ»ØÒ»¸öÖµ£¬Òò´ËÒ»°ãÖ»Äܼòµ¥µØ±êÖ¾³É¹¦»òʧ°Ü£¬¶øÎÞ·¨×÷Ϊ»ñÖª¾ßÌå´íÎóÐÅÏ¢µÄÊֶΡ£Í¨¹ý°´Î»±àÂë¿É±äͨµØ·µ»Ø¶à¸öÖµ£¬µ«²¢²»³£Óá£×Ö·û´®´¦Àíº¯Êý¿É²Î¿¼IntToAscii()À´·µ»Ø¾ßÌåµÄ´íÎóÔÒò£¬²¢Ö§³ÖÁ´Ê½±í´ï£º
char *IntToAscii(int dwVal, char *pszRes, int dwRadix)
{
if(NULL == pszRes)
return "Arg2Null";
if((dwRadix < 2) || (dwRadix > 36))
return "Arg3OutOfRange";
//...
return pszRes;
}
|
4) ¶¨Òå³åÍ»
²»Í¬º¯ÊýÔڳɹ¦ºÍʧ°Üʱ·µ»ØÖµµÄȡֵ¹æÔò¿ÉÄܲ»Í¬¡£ÀýÈ磬Unixϵͳµ÷Óü¶º¯Êý·µ»Ø0´ú±í³É¹¦£¬-1´ú±íʧ°Ü£»ÐµÄPosixº¯Êý·µ»Ø0´ú±í³É¹¦£¬·Ç0´ú±íʧ°Ü£»±ê×¼C¿âÖÐisxxxº¯Êý·µ»Ø1±íʾ³É¹¦£¬0±íʾʧ°Ü¡£
5) ÎÞÔ¼ÊøÐÔ
µ÷ÓÃÕß¿ÉÒÔºöÂԺͶªÆú·µ»ØÖµ¡£Î´¼ì²éºÍ´¦Àí·µ»ØÖµÊ±£¬³ÌÐòÈÔÈ»Äܹ»ÔËÐУ¬µ«½á¹û²»¿ÉÔ¤Öª¡£
еÄPosixº¯Êý·µ»ØÖµÖ»Ð¯´ø×´Ì¬ºÍÒì³£ÐÅÏ¢£¬²¢Í¨¹ý²ÎÊýÁбíÖеÄÖ¸Õë»Ø´«ÓÐÓõĽá¹û¡£ »Ø´«²ÎÊý°ó¶¨µ½ÏàÓ¦µÄʵ²ÎÉÏ£¬Òò´Ëµ÷ÓÃÕß²»¿ÉÄÜÍêÈ«ºöÂÔËüÃÇ¡£Í¨¹ý»Ø´«²ÎÊý(Èç½á¹¹ÌåÖ¸Õë)¿É·µ»Ø¶à¸öÖµ£¬Ò²¿ÉЯ´ø¸ü¶àµÄÐÅÏ¢¡£
×ۺϷµ»ØÖµºÍ»Ø´«²ÎÊýµÄÓŵ㣬¿É¶ÔGetÀຯÊý²ÉÓ÷µ»ØÖµ(º¬ÓÐÓýá¹û)·½Ê½£¬¶ø¶ÔSetÀຯÊý²ÉÓ÷µ»ØÖµ+»Ø´«²ÎÊý·½Ê½¡£¶ÔÓÚ´¿´âµÄ·µ»ØÖµ£¬¿É°´ÐèÌṩÈçϽâÎö½Ó¿Ú£º
typedef enum{ S_OK, //³É¹¦ S_ERROR, //ʧ°Ü(ÔÒòδÃ÷È·)£¬Í¨ÓÃ״̬
S_NULL_POINTER, //Èë²ÎÖ¸ÕëΪNULL
S_ILLEGAL_PARAM, //²ÎÊýÖµ·Ç·¨£¬Í¨ÓÃ
S_OUT_OF_RANGE, //²ÎÊýÖµÔ½ÏÞ
S_MAX_STATUS //²»¿É×÷Ϊ·µ»ØÖµ×´Ì¬£¬½ö×÷ö¾Ù×îֵʹÓÃ
}FUNC_STATUS;
#define RC_NAME(eRetCode) \
((eRetCode) == S_OK ? "Success" : \
((eRetCode) == S_ERROR ? "Failure" :
\
((eRetCode) == S_NULL_POINTER ? "NullPointer"
: \
((eRetCode) == S_ILLEGAL_PARAM ? "IllegalParas"
: \
((eRetCode) == S_OUT_OF_RANGE ? "OutOfRange"
: \
"Unknown"))))) |
µ±·µ»ØÖµ´íÎóÂëÀ´×ÔÏÂÓÎÄ£¿éʱ£¬¿ÉÄÜÓ뱾ģ¿é´íÎóÂë³åÍ»¡£´Ëʱ£¬½¨Òé²»Òª½«ÏÂÓδíÎóÂëÖ±½ÓÏòÉÏ´«µÝ£¬ÒÔÃâÒýÆð»ìÂÒ¡£ÈôÔÊÐíÏòÖÕ¶Ë»òÎļþÊä³ö´íÎóÐÅÏ¢£¬Ôò¿ÉÏêϸ¼Ç¼³ö´íÏÖ³¡(È纯ÊýÃû¡¢´íÎóÃèÊö¡¢²ÎÊýȡֵµÈ)£¬²¢×ª»»Îª±¾Ä£¿é¶¨ÒåµÄ´íÎóÂëÔÙÏòÉÏ´«µÝ¡£
2.2 È«¾Ö״̬±êÖ¾(errno)
Unixϵͳµ÷ÓûòijЩC±ê×¼¿âº¯Êý³ö´íʱ£¬Í¨³£·µ»ØÒ»¸ö¸ºÖµ£¬²¢ÉèÖÃÈ«¾ÖÕûÐͱäÁ¿errnoΪһ¸öº¬ÓдíÎóÐÅÏ¢µÄÖµ¡£ÀýÈ磬openº¯Êý³ö´íʱ·µ»Ø-1£¬²¢ÉèÖÃerrnoΪEACESS(ȨÏÞ²»×ã)µÈÖµ¡£
C±ê×¼¿âÍ·Îļþ<errno.h>Öж¨Òåerrno¼°Æä¿ÉÄܵķÇÁã³£Á¿È¡Öµ(ÒÔ×Ö·û'E'¿ªÍ·)¡£ÔÚANSI
CÖÐÒѶ¨ÒåһЩ»ù±¾µÄerrno³£Á¿£¬²Ù×÷ϵͳҲ»áÀ©Õ¹Ò»²¿·Ö(µ«Æä¶Ô´íÎóÃèÊöÈÔÏÔØÑ·¦)¡£LinuxϵͳÖУ¬³ö´í³£Á¿ÔÚerrno(3)ÊÖ²áÒ³ÖÐÁгö£¬¿Éͨ¹ýman
3 errnoÃüÁî²é¿´¡£³ýEAGAINºÍEWOULDBLOCKȡֵÏàͬÍ⣬POSIX.1Ö¸¶¨µÄËùÓгö´í±àºÅȡֵ¾ù²»Í¬¡£
PosixºÍISO C½«errno¶¨ÒåΪһ¸ö¿ÉÐ޸ĵÄÕûÐÍ×óÖµ(lvalue)£¬¿ÉÒÔÊǰüº¬³ö´í±àºÅµÄÒ»¸öÕûÊý£¬»òÊÇÒ»¸ö·µ»Ø³ö´í±àºÅÖ¸ÕëµÄº¯Êý¡£ÒÔǰʹÓõ͍ÒåΪ£º
µ«ÔÚ¶àÏ̻߳·¾³ÖУ¬¶à¸öÏ̹߳²Ïí½ø³ÌµØÖ·¿Õ¼ä£¬Ã¿¸öÏ̶߳¼ÓÐÊôÓÚ×Ô¼ºµÄ¾Ö²¿errno(thread-local)ÒÔ±ÜÃâÒ»¸öÏ̸߳ÉÈÅÁíÒ»¸öÏ̡߳£ÀýÈ磬LinuxÖ§³Ö¶àÏ̴߳æÈ¡errno£¬½«Æä¶¨ÒåΪ£º
extern int *__errno_location(void); 2 #define errno (*__errno_location()) |
º¯Êý__errno_locationÔÚ²»Í¬µÄ¿â°æ±¾ÏÂÓв»Í¬µÄ¶¨Ò壬ÔÚµ¥Ḭ̈߳汾ÖУ¬Ö±½Ó·µ»ØÈ«¾Ö±äÁ¿errnoµÄµØÖ·£»¶øÔÚ¶àḬ̈߳汾ÖУ¬²»Í¬Ï̵߳÷ÓÃ__errno_location·µ»ØµÄµØÖ·Ôò¸÷²»Ïàͬ¡£
CÔËÐпâÖÐÖ÷ÒªÔÚmath.h(ÊýѧÔËËã)ºÍstdio.h(I/O²Ù×÷)Í·ÎļþÉùÃ÷µÄº¯ÊýÖÐʹÓÃerrno¡£
ʹÓÃerrnoʱӦעÒâÒÔϼ¸µã£º
1) º¯Êý·µ»Ø³É¹¦Ê±£¬ÔÊÐíÆäÐÞ¸Äerrno¡£
ÀýÈ磬µ÷ÓÃfopenº¯Êýн¨Îļþʱ£¬ÄÚ²¿¿ÉÄÜ»áµ÷ÓÃÆäËû¿âº¯Êý¼ì²âÊÇ·ñ´æÔÚͬÃûÎļþ¡£¶øÓÃÓÚ¼ì²âÎļþµÄ¿âº¯ÊýÔÚÎļþ²»´æÔÚʱ£¬¿ÉÄÜ»áʧ°Ü²¢ÉèÖÃerrno¡£ÕâÑù£¬
fopenº¯Êýÿ´Îн¨Ò»¸öÊÂÏȲ¢²»´æÔÚµÄÎļþʱ£¬¼´Ê¹Ã»ÓÐÈκγÌÐò´íÎó·¢Éú(fopen±¾Éí³É¹¦·µ»Ø)£¬errnoÒ²ÈÔÈ»¿ÉÄܱ»ÉèÖá£
Òò´Ë£¬µ÷Óÿ⺯ÊýʱӦÏȼì²â×÷Ϊ´íÎóָʾµÄ·µ»ØÖµ¡£½öµ±º¯Êý·µ»ØÖµÖ¸Ã÷³ö´íʱ£¬²Å¼ì²éerrnoÖµ£º
//µ÷Óÿ⺯Êý 2 if(·µ»Ø´íÎóÖµ) 3 //¼ì²éerrno |
2) ¿âº¯Êý·µ»ØÊ§°Üʱ£¬²»Ò»¶¨»áÉèÖÃerrno£¬È¡¾öÓÚ¾ßÌåµÄ¿âº¯Êý¡£
3) errnoÔÚ³ÌÐò¿ªÊ¼Ê±ÉèÖÃΪ0£¬Èκο⺯Êý¶¼²»»á½«errnoÔÙ´ÎÇåÁã¡£
Òò´Ë£¬ÔÚµ÷ÓÿÉÄÜÉèÖÃerrnoµÄÔËÐп⺯Êý֮ǰ£¬×îºÃÏȽ«errnoÉèÖÃΪ0¡£µ÷ÓÃʧ°ÜºóÔÙ¼ì²éerrnoµÄÖµ¡£
4) ʹÓÃerrnoǰ£¬Ó¦±ÜÃâµ÷ÓÃÆäËû¿ÉÄÜÉèÖÃerrnoµÄ¿âº¯Êý¡£È磺
if (somecall() == -1) 2 { 3 printf("somecall() failed\n"); 4 if(errno == ...) { ... } 5 }
|
somecall()º¯Êý³ö´í·µ»ØÊ±ÉèÖÃerrno¡£µ«µ±¼ì²éerrnoʱ£¬ÆäÖµ¿ÉÄÜÒѱ»printf()º¯Êý¸Ä±ä¡£ÈôÒªÕýȷʹÓÃsomecall()º¯ÊýÉèÖõÄerrno£¬ÐëÔÚµ÷ÓÃprintf()º¯Êýǰ±£´æÆäÖµ£º
if (somecall() == -1) 2 { 3 int dwErrSaved = errno; 4 printf("somecall() failed\n"); 5 if(dwErrSaved == ...) { ... } 6 } |
ÀàËÆµØ£¬µ±ÔÚÐźŴ¦Àí³ÌÐòÖе÷ÓÿÉÖØÈ뺯Êýʱ£¬Ó¦ÔÚÆäǰ±£´æÆäºó»Ö¸´errnoÖµ¡£
5) ʹÓÃÏÖ´ú°æ±¾µÄC¿âʱ£¬Ó¦°üº¬Ê¹ÓÃ<errno.h>Í·Îļþ£»Ôڷdz£ÀϵÄUnix ϵͳÖУ¬¿ÉÄÜûÓиÃÍ·Îļþ£¬´Ëʱ¿ÉÊÖ¹¤ÉùÃ÷errno(Èçextern
int errno)¡£
C±ê×¼¶¨ÒåstrerrorºÍperrorÁ½¸öº¯Êý£¬ÒÔ°ïÖú´òÓ¡´íÎóÐÅÏ¢¡£
#include <string.h>
char *strerror(int errnum); |
¸Ãº¯Êý½«errnum(¼´errnoÖµ)Ó³ÉäΪһ¸ö³ö´íÐÅÏ¢×Ö·û´®£¬²¢·µ»ØÖ¸Ïò¸Ã×Ö·û´®µÄÖ¸Õë¡£¿É½«³ö´í×Ö·û´®ºÍÆäËüÐÅÏ¢×éºÏÊä³öµ½Óû§½çÃæ£¬»ò±£´æµ½ÈÕÖ¾ÎļþÖУ¬Èçͨ¹ýfprintf(fp,
"somecall failed(%s)", strerror(errno))½«´íÎóÏûÏ¢´òÓ¡µ½fpÖ¸ÏòµÄÎļþÖС£
perrorº¯Êý½«µ±Ç°errno¶ÔÓ¦µÄ´íÎóÏûÏ¢µÄ×Ö·û´®Êä³öµ½±ê×¼´íÎó(¼´stderr»ò2)ÉÏ¡£
#include <stdio.h>
void perror(const char *msg);
|
¸Ãº¯ÊýÊ×ÏÈÊä³öÓÉmsgÖ¸ÏòµÄ×Ö·û´®(Óû§×Ô¼º¶¨ÒåµÄÐÅÏ¢)£¬ºóÃæ½ô¸úÒ»¸öðºÅºÍ¿Õ¸ñ£¬È»ºóÊǵ±Ç°errnoÖµ¶ÔÓ¦µÄ´íÎóÀàÐÍÃèÊö£¬×îºóÊÇÒ»¸ö»»Ðзû¡£Î´Ê¹ÓÃÖØ¶¨Ïòʱ£¬¸Ãº¯ÊýÊä³öµ½¿ØÖÆÌ¨ÉÏ£»Èô½«±ê×¼´íÎóÊä³öÖØ¶¨Ïòµ½/dev/null£¬Ôò¿´²»µ½ÈκÎÊä³ö¡£
×¢Ò⣬perror()º¯ÊýÖÐerrno¶ÔÓ¦µÄ´íÎóÏûÏ¢¼¯ºÏÓëstrerror()Ïàͬ¡£µ«ºóÕß¿ÉÌṩ¸ü¶à¶¨Î»ÐÅÏ¢ºÍÊä³ö·½Ê½¡£
Á½¸öº¯ÊýµÄÓ÷¨Ê¾ÀýÈçÏ£º
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)! |
Ò²¿É·ÂÕÕerrnoµÄ¶¨ÒåºÍ´¦Àí£¬¶¨ÖÆ×Ô¼ºµÄ´íÎó´úÂ룺
int *_fpErrNo(void) { static int dwLocalErrNo = 0; return &dwLocalErrNo; }
#define ErrNo (*_fpErrNo())
#define EOUTOFRANGE 1
//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;
} |
½èÖúÈ«¾Ö״̬±êÖ¾£¬¿É³ä·ÖÀûÓú¯ÊýµÄ½Ó¿Ú(·µ»ØÖµºÍ²ÎÊý±í)¡£µ«Óë·µ»ØÖµÒ»Ñù£¬ËüÒþº¬µØÒªÇóµ÷ÓÃÕßÔÚµ÷Óú¯Êýºó¼ì²é¸Ã±êÖ¾£¬¶øÕâÖÖÔ¼ÊøÍ¬Ñù´àÈõ¡£
´ËÍ⣬ȫ¾Ö״̬±êÖ¾´æÔÚÖØÓú͸²¸ÇµÄ·çÏÕ¡£¶øº¯Êý·µ»ØÖµÊÇÎÞÃûµÄÁÙʱ±äÁ¿£¬Óɺ¯Êý²úÉúÇÒÖ»Äܱ»µ÷ÓÃÕß·ÃÎÊ¡£µ÷ÓÃÍê³Éºó¼´¿É¼ì²é»ò¿½±´·µ»ØÖµ£¬È»ºóÔʼµÄ·µ»Ø¶ÔÏó½«Ïûʧ¶ø²»Äܱ»ÖØÓá£ÓÖÒòΪÎÞÃû£¬·µ»ØÖµ²»Äܱ»¸²¸Ç¡£
2.3 ¾Ö²¿Ìø×ª(goto)
ʹÓÃgotoÓï¾ä¿ÉÖ±½ÓÌø×ªµ½º¯ÊýÄڵĴíÎó´¦Àí´úÂë´¦¡£ÒÔ³ýÁã´íÎóΪÀý£º
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;
} |
Ö´Ðнá¹ûÈçÏ£º
[wangxiaoyuan_@localhost test1]$ ./test Enter the dividend: 10 Enter the divisor : 0 The divisor cannot be 0! [wangxiaoyuan_@localhost test1]$ ./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;
} |
2.4 ·Ç¾Ö²¿Ìø×ª(setjmp/longjmp)
¾Ö²¿gotoÓï¾äÖ»ÄÜÌøµ½ËùÔÚº¯ÊýÄÚ²¿µÄ±êºÅÉÏ¡£ÈôÒª¿çÔ½º¯ÊýÌø×ª£¬ÐèÒª½èÖú±ê×¼C¿âÌṩ·Ç¾Ö²¿Ìø×ªº¯Êýsetjmp()ºÍlongjmp()¡£ËüÃÇ·Ö±ð³Ðµ£·Ç¾Ö²¿±êºÅºÍgotoµÄ×÷Ó㬷dz£ÊÊÓÃÓÚ´¦Àí·¢ÉúÔÚÉî²ãǶÌ׺¯Êýµ÷ÓÃÖеijö´íÇé¿ö¡£¡°·Ç¾Ö²¿Ìø×ª¡±ÊÇÔÚÕ»ÉÏÌø¹ýÈô¸Éµ÷ÓÃÖ¡£¬·µ»Øµ½µ±Ç°º¯Êýµ÷Ó÷¾¶ÉϵÄij¸öº¯ÊýÄÚ¡£
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env,int val); |
º¯Êýsetjmp()½«³ÌÐòÔËÐÐʱµÄµ±Ç°ÏµÍ³¶ÑÕ»»·¾³±£´æÔÚ»º³åÇøenv½á¹¹ÖС£³õ´Îµ÷Óøú¯Êýʱ·µ»ØÖµÎª0¡£longjmp()º¯Êý¸ù¾Ýsetjmp()Ëù±£´æµÄenv½á¹¹»Ö¸´ÏÈǰµÄ¶ÑÕ»»·¾³£¬¼´¡°Ìø»Ø¡±ÏÈǰµ÷ÓÃsetjmpʱµÄ³ÌÐòÖ´Ðе㡣´Ëʱ£¬setjmp()º¯Êý·µ»Ølongjmp()º¯ÊýËùÉèÖõIJÎÊývalÖµ£¬³ÌÐò½«¼ÌÐøÖ´ÐÐsetjmpµ÷ÓúóµÄÏÂÒ»ÌõÓï¾ä(·Â·ð´ÓδÀ뿪setjmp)¡£²ÎÊývalΪ·Ç0Öµ£¬ÈôÉèÖÃΪ0£¬Ôòsetjmp()º¯Êý·µ»Ø1¡£
¿É¼û£¬setjmp()ÓÐÁ½Àà·µ»ØÖµ£¬ÓÃÓÚÇø·ÖÊÇÊ×´ÎÖ±½Óµ÷ÓÃ(·µ»Ø0)ºÍ»¹ÊÇÓÉÆäËûµØ·½Ìø×ª¶øÀ´(·µ»Ø·Ç0Öµ)¡£¶ÔÓÚÒ»¸ösetjmp¿ÉÓжà¸ölongjmp£¬Òò´Ë¿ÉÓɲ»Í¬µÄ·Ç0·µ»ØÖµÇø·ÖÕâЩlongjmp¡£
¾Ù¸ö¼òµ¥Àý×Ó˵Ã÷ setjmp/longjmpµÄ·Ç¾Ö²¿Ìø×ª£º
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 2 Enter Func1 3 Enter Func2 4 Enter Func3 5 dwJmpRet = 3 6 Jump back from Func3 |
µ±setjmp/longjmpǶÔÚµ¥¸öº¯ÊýÖÐʹÓÃʱ£¬¿ÉÄ£ÄâPASCALÓïÑÔÖÐǶÌ׺¯Êý¶¨Òå(¼´º¯ÊýÄÚÖж¨ÒåÒ»¸ö¾Ö²¿º¯Êý)¡£µ±setjmp/longjmp¿çÔ½º¯ÊýʹÓÃʱ£¬¿ÉÄ£ÄâÃæÏò¶ÔÏóÓïÑÔÖеÄÒì³£(exception)
»úÖÆ¡£
Ä£ÄâÒì³£»úÖÆÊ±£¬Ê×ÏÈͨ¹ýsetjmp()º¯ÊýÉèÖÃÒ»¸öÌø×ªµã²¢±£´æ·µ»ØÏÖ³¡£¬È»ºóʹÓÃtry¿é°üº¬ÄÇЩ¿ÉÄܳöÏÖ´íÎóµÄ´úÂë¡£¿ÉÔÚtry¿é´úÂëÖлòÆäµ÷Óõĺ¯ÊýÄÚ£¬Í¨¹ýlongjmp()º¯ÊýÅ׳ö(throw)Òì³£¡£Å׳öÒì³£ºó£¬½«Ìø»Øsetjmp()º¯ÊýËùÉèÖõÄÌø×ªµã²¢Ö´ÐÐcatch¿éËù°üº¬µÄÒì³£´¦Àí³ÌÐò¡£
ÒÔ³ýÁã´íÎóΪÀý£º
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 2 Enter the divisor : 0 3 Exception is raised: The divisor cannot be 0! |
ͨ¹ý×éºÏʹÓÃsetjmp/longjmpº¯Êý£¬¿É¶Ô¸´ÔÓ³ÌÐòÖпÉÄܳöÏÖµÄÒì³£½øÐм¯Öд¦Àí¡£¸ù¾Ýlongjmp()º¯ÊýËù´«µÝµÄ·µ»ØÖµÀ´Çø·Ö´¦Àí¸÷ÖÖ²»Í¬µÄÒì³£¡£
ʹÓÃsetjmp/longjmpº¯ÊýʱӦעÒâÒÔϼ¸µã£º
1) ±ØÐëÏȵ÷ÓÃsetjmp()º¯Êýºóµ÷ÓÃlongjmp()º¯Êý£¬ÒÔ»Ö¸´µ½ÏÈǰ±»±£´æµÄ³ÌÐòÖ´Ðе㡣Èôµ÷ÓÃ˳ÐòÏà·´£¬½«µ¼Ö³ÌÐòµÄÖ´ÐÐÁ÷±äµÃ²»¿ÉÔ¤²â£¬ºÜÈÝÒ×µ¼Ö³ÌÐò±ÀÀ£¡£
2) longjmp()º¯Êý±ØÐëÔÚsetjmp()º¯ÊýµÄ×÷ÓÃÓòÖ®ÄÚ¡£ÔÚµ÷ÓÃsetjmp()º¯Êýʱ£¬Ëü±£´æµÄ³ÌÐòÖ´Ðе㻷¾³Ö»ÔÚµ±Ç°Ö÷µ÷º¯Êý×÷ÓÃÓòÒÔÄÚ(»òÒÔºó)ÓÐЧ¡£ÈôÖ÷µ÷º¯Êý·µ»Ø»òÍ˳öµ½Éϲã(»ò¸üÉϲã)µÄº¯Êý»·¾³ÖУ¬Ôòsetjmp()º¯ÊýËù±£´æµÄ³ÌÐò»·¾³Ò²ËæÖ®Ê§Ð§(º¯Êý·µ»ØÊ±¶ÑÕ»ÄÚ´æÊ§Ð§)¡£Õâ¾ÍÒªÇósetjmp()²»¿É¸Ã·â×°ÔÚÒ»¸öº¯ÊýÖУ¬ÈôÒª·â×°Ôò±ØÐëʹÓúê(Ïê¼û¡¶CÓïÑÔ½Ó¿ÚÓëʵÏÖ¡·¡°µÚ4ÕÂ
Òì³£Óë¶ÏÑÔ¡±)¡£
3) ͨ³£½«jmp_buf±äÁ¿¶¨ÒåΪȫ¾Ö±äÁ¿£¬ÒÔ±ã¿çº¯Êýµ÷ÓÃlongjmp¡£
4) ͨ³££¬´æ·ÅÔÚ´æ´¢Æ÷ÖеıäÁ¿½«¾ßÓÐlongjmpʱµÄÖµ£¬¶øÔÚCPUºÍ¸¡µã¼Ä´æÆ÷ÖеıäÁ¿Ôò»Ö¸´Îªµ÷ÓÃsetjmpʱµÄÖµ¡£Òò´Ë£¬ÈôÔÚµ÷ÓÃsetjmpºÍlongjmpÖ®¼äÐÞ¸Ä×Ô¶¯±äÁ¿»ò¼Ä´æÆ÷±äÁ¿µÄÖµ£¬µ±setjmp´Ólongjmpµ÷Ó÷µ»ØÊ±£¬±äÁ¿½«Î¬³ÖÐ޸ĺóµÄÖµ¡£ÈôÒª±àдʹÓ÷Ǿֲ¿Ìø×ªµÄ¿ÉÒÆÖ²³ÌÐò£¬±ØÐëʹÓÃvolatileÊôÐÔ¡£
5) ʹÓÃÒì³£»úÖÆ²»±ØÃ¿´Îµ÷Óö¼¼ì²éÒ»´Î·µ»ØÖµ£¬µ«ÒòΪ³ÌÐòÖÐÈκÎλÖö¼¿ÉÄÜÅ׳öÒì³££¬±ØÐëʱ¿Ì¿¼ÂÇÊÇ·ñ²¶×½Òì³£¡£ÔÚ´óÐͳÌÐòÖУ¬ÅжÏÊÇ·ñ²¶×½Òì³£»áÊǺܴóµÄ˼ά¸ºµ££¬Ó°Ï쿪·¢Ð§ÂÊ¡£Ïà±È֮ϣ¬Í¨¹ý·µ»ØÖµÖ¸Ê¾´íÎóÓÐÀûÓÚµ÷ÓÃÕßÔÚ×î½ü³ö´íµÄµØ·½½øÐмì²é¡£´ËÍ⣬·µ»ØÖµÄ£Ê½ÖгÌÐòµÄÔËÐÐ˳ÐòһĿÁËÈ»£¬¶Ôά»¤Õ߿ɶÁÐÔ¸ü¸ß¡£Òò´Ë£¬Ó¦ÓóÌÐòÖв»½¨ÒéʹÓÃsetjmp/longjmp¡°Òì³£´¦Àí¡±»úÖÆ(³ý·Ç¿â»ò¿ò¼Ü)¡£
|