如果一个公司开发流程规范,注重代码的积累,基础库肯定是和承载的上层业务逻辑分开的,那么应该如何处理基础库的内部错误信息,以反馈给上层的业务逻辑呢?其中有一个原则要遵守:方便上层的调试,及发生错误时的定位。解决这样问题的一个思路是:其它库是怎么做的?聪明的你肯定想到了errno,及
GetLastError。
对,使用线程专有存储。下面是linux下的示例
1#include <stdio.h>
2#include <string.h>
3#include <pthread.h>
4#include <unistd.h>
5
6pthread_key_t key;
7
8struct SError
9{
10 int code;
11 char msg[512];
12};
13
14void SetErrInfo(const int nCode,const char* pMsg)
15{
16 SError* pErr = (SError*)pthread_getspecific(key);
17 if(pErr == NULL)
18 {//该线程还没有分配错误信息的内存
19 pErr = new SError();
20 pErr->code = nCode;
21 strcpy(pErr->msg,pMsg);
22 pthread_setspecific(key,(void*)pErr);
23 }
24 else
25 {
26 pErr->code = nCode;
27 strcpy(pErr->msg,pMsg);
28 }
29 return;
30}
31const char* GetErrMsg()
32{
33 SError* pErr = (SError*)pthread_getspecific(key);
34 if(pErr == NULL)
35 return NULL;
36 else
37 return pErr->msg;
38}
39const int GetErrCode()
40{
41 SError* pErr = (SError*)pthread_getspecific(key);
42 if(pErr == NULL)
43 return 0;
44 else
45 return pErr->code;
46}
47
48void echomsg(SError* t)
49{
50 printf("destructor excuted in thread %u,code = %d,msg = %s\n",pthread_self(),t->code,t->msg);
51 delete t;//前面传入的是内存的地址。所以可以delete
52}
53void * child1(void *arg)
54{
55 int tid=pthread_self();
56 printf("thread %u enter\n",tid);
57 SetErrInfo(0,"OK");
58 sleep(2);
59 printf("thread= %u,code = %d , msg = %s\n",tid,GetErrCode(),GetErrMsg());
60 sleep(5);
61}
62
63void * child2(void *arg)
64{
65 int tid=pthread_self();
66 printf("thread %u enter\n",tid);
67 SetErrInfo(1,"bad");
68 sleep(2);
69 printf("thread= %u,code = %d , msg = %s\n",tid,GetErrCode(),GetErrMsg());
70 sleep(2);
71 SetErrInfo(2,"bad2");
72 printf("thread= %u,code = %d , msg = %s\n",tid,GetErrCode(),GetErrMsg());
73}
74
75int main(void)
76{
77 int tid1,tid2;
78 printf("hello\n");
79 pthread_key_create(&key,(void (*)(void*))echomsg);
80 pthread_create((pthread_t *)&tid1,NULL,child1,NULL);
81 pthread_create((pthread_t *)&tid2,NULL,child2,NULL);
82 sleep(10);
83 pthread_key_delete(key);
84 printf("main thread exit\n");
85 return 0;
86}
1.开发中可以重载多个SetErrInfo,实现sprintf的格式化字符串功能;
2.基础库本身只需导出GetErrMsg和GetErrCode两个接口,比单纯用返回值来判断错误灵活的多
3.windows下可用Tls*系列api实现