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)开辟的内存没有释放.造成内存泄露,以下的样 ...
随机推荐
- sshd_config配置 详解
原文:http://blog.licess.org/sshd_config/ # 1. 关于 SSH Server 的整体设定,包含使用的 port 啦,以及使用的密码演算方式 Port 22 # S ...
- HDU 1465 不容易系列之一(错排,递归)
简而言之,就是把n个信封全部装错的可能数.(中问题,具体看题目) //当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用M(n)表示, //那么M(n-1)就表示n-1个编号元素放在 ...
- iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行
可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行. 前面提到可以将NSTimer手动加 ...
- Node.js缓冲模块Buffer
前言 Javascript是为浏览器而设计的,能很好的处理unicode编码的字符串,但对于二进制或非unicode编码的数据就显得无能为力. Node.js继承Javascript的语言特性,同时又 ...
- 快速幂取模 POJ 3761 bubble sort
题目传送门 /* 题意:求冒泡排序扫描k次能排好序的全排列个数 数学:这里有一个反序列表的概念,bj表示在j左边,但大于j的个数.不多说了,我也是看网上的解题报告. 详细解释:http://blog. ...
- JSTL Tag学习笔记(二)之<fmt: />
JSTL的formatting tags可以用来格式化和显示文本.日期.时间.数字.如果在JSP页面中要用到该库提供的tag的话,需要引入如下taglib: <%@ taglib prefix= ...
- 如何搭建配置php开发环境
PHP的配置 1.打开解压后的C:\Program Files (x86)\php-5.3.5文件夹 1 将php.ini-development文件并更改名称为php.ini(留个备份,好习惯) 2 ...
- jquery.lazyload用法
lazyload是jquery的插件,作为延迟加载图片,减压服务器压力. 如何使用: 先把 <script src="jquery.js" type="text/j ...
- 移动设备中导入gdb调试工具
(1)概述 接ADB调试桥安装(方式一),ADB调试桥安装好了后一般的移动设备内都不含有gdb工具, 要想使用gdb工具可以借助adb的push参数进行上传. gdb分为gdb客户端和服务端,文件可以 ...
- scala函数式编程
1.作为值的函数 在Scala中,函数和数字一样,可以在变量中存放函数.可以把函数赋值给一个变量,格式为:val foee=fun _(函数名+空格+_)形式 2.匿名函数 在scala中,不需要给每 ...