【内存类操作】浅谈内存拷贝异常

来源:互联网 发布:1hhhh.com域名升级 编辑:程序博客网 时间:2024/05/27 19:27

    结合本人在实际项目中所积累的经验,以及曾经犯过的错误,堆内存操作类函数做一个简单的剖析,抛砖引玉,欢迎大家吐槽。

    首先,讲一下内存使用异常发生的几种场景。

                1、野指针的使用,使用已经释放的指针,如果向野指针中写内容,就极有可能导致设备重启或任务挂死。因为,正在运行的任务的地址被意外的改写。

                     【避免策略】函数入参要判空,指针使用(包括释放)之前一定要释放。

                2、内存函数的错误使用:

                       void *memset(void *s, int ch, size_t n);  

                           c语言中在<memory.h><string.h>c++中是在<cstring>作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。

                       【异常情况】如果n的长度 大于指针 s的长度,则会出现内存操作越界现象,同样可能导致设备重启或任务挂死。

                       【避免策略】确保n 的长度 小于等于 指针s 指向内存的长度。

               3、内存拷贝的函数 memcpy:src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。

                           void *memcpy(void *dest,const void *src, int n);c语言中在<memory.h><string.h>c++中是在<cstring>strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

                      【异常情况】从src指向的内存拷贝的长度 大于 dest指向的内存长度。

                      【避免策略】除了人为保证 拷贝长度 小于等于 dest指向的内存长度之外,可以封装一个安全函数

                        void *memcpy_safe(void *dest, ulong ulDeLen, void *src, ulong ulSrcLen)

                        {

                                         if(ulDeLen < ulSrcLen)   //确保不会超过目的内存块大小

                                         {

                                                   assert();

                                                   return NULL;

                                         }

                                         memcpy(dest,src,ulSrcLen);

                         }  其中ulDeLen 指定目的内存的长度,ulSrcLen 指定要拷贝内存的长度

                4、Memcmp: 比较内存区域buf1buf2count个字节。(区别于strcmp)

                          int memcmp(const void*buf1, const void *buf2, unsigned int count);c语言中在<memory.h><string.h>c++中是在<cstring>。注意:比较的时候比较的是字节,字母的时候比较的是字母的ASCII,大的就是大,小的就小。

                     【异常情况】错误的以为该比较函数可以比较两个字符串 比如:

                           char *buf1   = (char *)malloc(10);

                           char *buf2  = (char *)malloc(10);

                           buf1 =  "ab";

                           buf2 =  "ab";

                           memcmp(buf1,buf2,10);   // 无法判断谁大谁小  ,因为buf1与buf2申请之后没有清零,ab之后的内存区域可以为任意值

                          如果  memset(buf1, 0, 10); 

                                   memset(buf2, 0, 10);

                                   buf1 = "abcd";

                                   buf2 = "abc";

                                   buf1 = "a";

                                   buf2 = "a";

                                   memcmp(buf1,buf2,10); //buf1 != buf2

参考函数:

#include "stdio.h"#include "memory.h"#include "stdlib.h"int main (){unsigned char *ucBufOne;unsigned char *ucBufTwo;    ucBufOne = (unsigned char *) malloc(10);    ucBufTwo = (unsigned char *) malloc(10);    memcpy(ucBufOne, "ab", 2);    memcpy(ucBufTwo, "ab", 2);    printf("Result = %d",memicmp(ucBufOne,ucBufTwo,10));    getchar();}


                 5、Strcpy:字符数组复制

                       char *strcpy(char* dest, const char *src);  //将字符串从src中拷贝到dest中

                       char *strncpy(char*dest, const char *src, size_t n);// 从src中拷贝n个字符到dest中

                       【异常情况】拷贝的长度大于dest缓冲区长度

                       【避免策略】封装成安全函数 strncpy_safe(char *dest, size_t n1, char *src, size_t n2);  //具体实现自己思考

                 6、Strcat:连接两个字符数组

                       char *strcat(char *dest,char *src);   //将字符串src 链接到 dest后面

                       char *strncat(char *dest,char *src,int n); 

                       异常情况及避免策略同上

                 7、Strcmp:比较两个字符数组

                       int strcmp(const char *s1,const char * s2);  //遇到"\0"停止比较

                       int strncmp(char *str1, char *str2, int maxlen);  //比较maxlen个字符

                       异常情况及避免策略同上

 

    

                          

 

                        

                     

 

 

3 0
原创粉丝点击