C语言之内存覆盖
在实现memcpy函数的时候,我们说过要考虑内存覆盖的问题,到底什么是内存覆盖呢,他的出现对程序到底有什么影响呢?我们又要如何去解决这种问题的发生?
首先先看一般人经常实现的memcpy函数:
#include<stdio.h>
#include<assert.h>
#include<string.h>
void *my_memcpy(void *dest, const void *src, size_t count)
{
assert(dest!=NULL || src!=NULL);
char *ptmpDest = (char *)dest;
const char *ptmpSrc = (const char *)src;
while(count-- > 0)
{
*ptmpDest++ = *ptmpSrc++;
}
return dest;
}
乍一看这段代码,好像很有道理,经过一些测试也是对的,但程序到底是哪里出了问题呢?首先我们来测试一下:
void main()
{
char str[20] = "abcdefghij";
char str1[20];
my_memcpy(str1,str,strlen(str)+1);//正确拷贝
printf("str1 = %s\n",str1);
my_memcpy(str+2,str,4);//错误,拷贝出现了内存覆盖
printf("str = %s\n",str);
}
我们发现当字符串自己给自己赋值时,当目标字符串大于源字符串要拷贝的字符的个数时,程序就会出现错误,这里就涉及到了内存覆盖问题。
我们首先分析源字符串与目标字符串之间的关系:

while(count-- > 0)
{
*(ptmpDest + count) = *(ptmpSrc + count);
}
我们再来分析其他五种情况,可以得出他们的判断条件是:
ptmpSrc >= ptmpDest || ptmpDest >= ptmpSrc+count
只要满足上面的条件就不需要考虑内存重叠的问题,所以实现整体自己实现memcpy的函数代码为:
#include<stdio.h>
#include<assert.h>
#include<string.h>
void *my_memcpy(void *dest, const void *src, size_t count)
{
assert(dest!=NULL || src!=NULL);
char *ptmpDest = (char *)dest;
const char *ptmpSrc = (const char *)src;
//源地址在目的地址的右边,或者目的地址在源地址的右边,但没有交集
//直接拷贝
if(ptmpSrc >= ptmpDest || ptmpDest >= ptmpSrc+count)
{
while(count-- > 0)
{
*ptmpDest++ = *ptmpSrc++;
}
}
else //源地址在目的地址左边,并产生交集,形成内存覆盖,反着拷贝
{
while(count-- > 0)
{
*(ptmpDest + count) = *(ptmpSrc + count);
}
}
return dest;
}
C语言之内存覆盖的更多相关文章
- C语言和内存
1.程序的运行 对cpu来说,内存只是一个存放指令和数据的地方,具体的运算在cpu内完成. 1.寄存器(Register) 是CPU内部非常小.非常快速的存储部件,它的容量很有限,对于32位的CPU, ...
- 记一次难忘的排错debug经历(找了5天左右)(涉及内存覆盖)
strcpy和memcpy都没有处理内存覆盖问题. 函数描述 The memcpy function copies count bytes of src to dest. If the source ...
- C语言中内存的申请函数
C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等. alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且 ...
- JVM内存管理------JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- 不可或缺 Windows Native (9) - C 语言: 动态分配内存,链表,位域
[源码下载] 不可或缺 Windows Native (9) - C 语言: 动态分配内存,链表,位域 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 动态分配内存 链 ...
- c语言之内存的申请malloc() 和释放free()
c语言之内存的申请malloc() 和释放free() 1.如何使用 malloc 函数 malloc是一个函数,专门用来从堆上分配内存.使用malloc函数需要几个要求: 内存分配给谁?分配多大内存 ...
- C语言的内存管理
C语言的内存管理 转载:http://blog.csdn.net/wind19/article/details/5964090 对于一个C语言程序而言,内存空间主要由五个部分组成代码段(.text ...
- (十一)C语言中内存堆和栈的区别
在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念. 堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认 ...
- C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针
C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...
随机推荐
- Sqli-labs less 47
Less-47 本关的sql语句为 $sql = "SELECT * FROM users ORDER BY '$id'"; 将id变为字符型,因此根据我们上述提到的知识,我 ...
- ubuntu修改ip、网关、dns等
一.使用命令设置Ubuntu IP地址 1.修改配置文件blacklist.conf禁用IPV6 sudo vi /etc/modprobe.d/blacklist.conf 表示用vi编辑器(也可以 ...
- chrome 网络面板
Chrome Timeline的指标说明:Blocked.Connect.Send.Wait.Receive Blocked time includes any pre-processing time ...
- 用于主题检测的临时日志(b42e98ba-eb4f-4099-a54c-7aee3f29c3dd - 3bfe001a-32de-4114-a6b4-4005b770f6d7)
这是一个未删除的临时日志.请手动删除它.(184c28c9-c88e-48fe-9713-6891e2d15044 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)
- POJ 3255
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6605 Accepted: 2458 Descri ...
- 2013 ACM/ICPC Asia Regional Online —— Warmup
1003 Rotation Lock Puzzle 找出每一圈中的最大值即可 代码如下: #include<iostream> #include<stdio.h> #inclu ...
- JS中的this好神奇,都把我弄晕了
一.this的常见判断: 1.函数预编译过程 this —> window 2.全局作用域里 this —> window 3.call/apply 可以改变函数运行时this指向 4.o ...
- 矩阵快速幂 POJ 3735 Training little cats
题目传送门 /* 题意:k次操作,g:i猫+1, e:i猫eat,s:swap 矩阵快速幂:写个转置矩阵,将k次操作写在第0行,定义A = {1,0, 0, 0...}除了第一个外其他是猫的初始值 自 ...
- 李洪强iOS开发之UICollectionView的使用
想做如下的界面效果(纯代码) ------------------------------------------------------------------------------------ ...
- POJ2126——Prime Path(BFS)
Prime Path DescriptionThe ministers of the cabinet were quite upset by the message from the Chief of ...