【内存类操作】浅谈内存拷贝异常
来源:互联网 发布: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: 比较内存区域buf1和buf2的前count个字节。(区别于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个字符
异常情况及避免策略同上
- 【内存类操作】浅谈内存拷贝异常
- 浅谈CUDA零拷贝内存
- 拷贝函数和内存操作拷贝
- 内存拷贝
- 内存拷贝
- 内存拷贝
- 两个内存进行拷贝时的操作
- 内存异常
- 内存拷贝和字符串拷贝
- C语言基础知识之(十九):内存操作的其他函数:内存初始化,内存拷贝,内存比较
- 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
- 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
- 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
- 为需要动态分配内存的类声明一个拷贝构造函数和赋值操作符
- 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
- C/C++--字符串拷贝及内存操作(转载)
- C/C++--字符串拷贝及内存操作(转载)
- 【C语言】 字符串操作函数及内存拷贝函数归总
- JavaScript获取路径
- Android dump的使用2
- 权重矩阵
- 《Java程序员面试笔试宝典》之为什么Java中有些接口没有任何方法
- Swing
- 【内存类操作】浅谈内存拷贝异常
- 取石子游戏2
- 移植Realtek USB无线网卡到 mini2440
- C#基础知识概念
- 避免Spring产生两个Context的做法
- 求数组元素的最大值最小值
- Unity3D游戏开发从零单排(五) - 导入CS模型到Unity3D
- 关于修改窗口的外观,图标,光标,背景的方法
- 使用Java实现万年历的格式打印