...
13 ? ? /*28 */ ? ? "GetCurData",
14 ? ? /*29 */ ? ? "SetTable"
15 };
16 const static unsigned char ucMsgNameNum = sizeof(paMsgNameMap) / sizeof(paMsgNameMap[0]);
17?
18 char *ParseOmciMsgType(unsigned char ucMsgType)
19 {
20 ? ? if(ucMsgType < ucMsgNameNum)
21 ? ? ? ? return paMsgNameMap[ucMsgType];
22?
23 ? ? char szStrMsgType[sizeof("255")] = {0}; ?/* Max:"255" */
24 ? ? sprintf(szStrMsgType, "%u", ucMsgType);
25 ? ? return szStrMsgType; ?//编译警告:
26 }
复制代码
? ? ?编译上述代码,函数ParseOmciMsgType在返回szStrMsgType处产生function returns address of local variable的警告。可将szStrMsgType定义为静态变量:
?
复制代码
1 char *ParseOmciMsgType(unsigned char ucMsgType)
2 {
3 ? ? if(ucMsgType < ucMsgNameNum)
4 ? ? ? ? return paMsgNameMap[ucMsgType];
5?
6 ? ? static char szStrMsgType[sizeof("255")] = {0}; /* Max:"255" */
7 ? ? sprintf(szStrMsgType, "%u", ucMsgType);
8 ? ? return szStrMsgType;
9 }
复制代码
? ? ?若将结果通过函数参数而非返回值传递,则代码会更为安全:
?
复制代码
1 void ParseOmciMsgType(unsigned char ucMsgType, char *pszMsgType)
2 {
3 ? ? if(ucMsgType < ucMsgNameNum)
4 ? ? ? ? strcpy(pszMsgType, paMsgNameMap[ucMsgType]);
5 ? ? else
6 ? ? ? ? sprintf(pszMsgType, "%u", ucMsgType);
7 }
复制代码
? ? ?注意,不可采用下面的写法:
?
复制代码
1 void ParseOmciMsgType(unsigned char ucMsgType, char *pszMsgType)
2 {
3 ? ? if(ucMsgType < ucMsgNameNum)
4 ? ? ? ? pszMsgType = paMsgNameMap[ucMsgType];
5 ? ? else
6 ? ? ? ? sprintf(pszMsgType, "%u", ucMsgType);
7 }
复制代码
? ? ?因为指针做为函数参数时,函数内部只能改变指针所指向地址的内容,并不能改变指针的指向。
?
? ? ?若线程在自身栈上分配一个数据结构并将指向该结构的指针传递给pthread_exit,则调用pthread_join的线程试图使用该结构时,原先的栈区内存可能已被释放或另作他用。
?
? ? 【对策】不要用return语句返回指向栈内变量的指针,可改为返回指向静态变量或动态内存的指针。但两者都存在重入性问题,而且后者还存在内存泄露的危险。
?
?
?
2.3 堆区内存
2.3.1 内存未初始化
? ? ?通过malloc库函数分配的动态内存,其初值未定义。若访问未初始化或未赋初值的内存,则会获得垃圾值。当基于这些垃圾值控制程序逻辑时,会产生不可预测的行为。
?
? ? 【对策】在malloc之后调用 memset 将内存初值清零,或使用 calloc代替malloc。
?
1 char *pMem = malloc (10);
2 memset(pMem, 0, 10); // memset前应对申请的动态内存做有效性检查
3 //Or
4 char *pMem = calloc (10, 1);
2.3.2 内存分配失败
? ? ?动态内存成功分配的前提是系统具有足够大且连续可用的内存。内存分配失败的主要原因有:
?
? ? ?1) 剩余内存空间不足;
?
? ? ?2) 剩余内存空间充足,但内存碎片太多,导致申请大块内存时失败;
?
? ? ?3) 内存越界,导致malloc等分配函数所维护的管理信息被破坏。
?
? ? ?剩余内存空间不足的情况相对少见,通常发生在申请超大块内存时。例如:
?
复制代码
?1 #include
?2 #include
?3 #define ALLOC_BYTES ? (1024*1024*1024)
?4 int main(void){
?5 ? ? unsigned int dwRound = 0;
?6 ? ? while(1){
?7 ? ? ? ? char *pMem = malloc(ALLOC_BYTES);
?8 ? ? ? ? if(NULL == pMem){
?9 ? ? ? ? ? ? printf("Alloc failed(%s)!\n", strerror(errno));
10 ? ? ? ? ? ? return -1;?
11 ? ? ? ? }?
12 ? ? ? ? printf("%d -> 0x%p\n", dwRound, pMem);?
13 ? ? ? ? dwRound++;
14 ? ? }
15 ? ? return 0;
16 }
复制代码
? ? ?执行后产生内存分配失败的错误:
?
1 0 -> 0x77f6b008
2 1 -> 0x37f6a008
3 Alloc failed(Cannot allocate memory)!
? ? ?内存越界导致内存分配失败的情况更为常见。此时,可从分配失败的地方开始回溯最近那个分配成功的malloc,看附近是否存在内存拷贝和数组越界的操作。
?
? ? 【对策】若申请的内存单位为吉字节(GigaByte),可考虑选用64位寻址空间的机器,或将数据暂存于硬盘文件中。此外,申请动态内存后,必须判断内存是否是为NULL,并进行防错处理,比如使用return语句终止本函数或调用exit(1)终止整个程序的运行。
?
2.3.3 内存释放失败
? ? ?内存释放失败的主要原因有:
?
? ? ?1) 释放未指向动态内存的指针;
?
? ? ?2) 指向动态内存的指针在释放前被修改;
?
? ? ?3) 内存越界,导致malloc等分配函数所维护的管理信息被破坏;
?
? ? ?4) 内存重复释放(Double Free)。
?
? ? ?情况1属于低级错误,即指针并未执行malloc分配,却调用free释放该指针指向的内存。
?
复制代码
1 int main(void)
2 {
3 ? ? int dwMem = 0; //具有迷惑性的变量名
4 ? ? int *pBuf = &dwMem;
5 ? ? free