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)开辟的内存没有释放.造成内存泄露,以下的样 ...
随机推荐
- logback日志配置文件代码示例
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true&q ...
- Properties的用法
/** * Description:Properties是HashTable的子類,其存儲形式鍵值對. */ import java.util.*; public class PropertysTes ...
- elasticsearch 八、重要的配置更改
http://jingyan.baidu.com/article/7908e85c9fc626af491ad263.html
- (转)白话经典算法系列之八 MoreWindows白话经典算法之七大排序总结篇
在我的博客对冒泡排序,直接插入排序,直接选择排序,希尔排序,归并排序,快速排序和堆排序这七种常用的排序方法进行了详细的讲解,并做成了电子书以供大家下载.下载地址为:http://download.cs ...
- [转载]U3d常规性能优化技巧
以下技巧并不是必须的,但是对于想要提升游戏性能的人来说应该还是很不错的. 优化的常规技巧 n 剖析你的游戏. 不要花费时间来优化那些晦涩的代码或者缩减图形文件的大小,除非这是你游戏的瓶颈.第一次剖析你 ...
- C. Tourist's Notes
题目链接 题意:n天内登山,相邻两次登山的高度差的绝对值小于等于1,也就是说每次高度变化只能是:0,1,-1.我们已经知道n天中部分天数人所在的山的高度,求最大的登山高度. 输入: n m n 是天 ...
- TCP三次握手和四次挥手协议
相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助. TCP三次握手 所谓三次握手( ...
- 【PSR规范专题(5)】PSR-4 改进后的自动加载规范
本文转自: https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md 关键词 "必须"(&quo ...
- jsp中如何用jstl实现if(){}else if(){}else{}
<c:choose> <c:when test="${条件}"> 情况1........... </c:when> <c:when tes ...
- android 点九PNG技术 适应不同分辨率 完美显示效果
.9.png是一种非失真性压缩位图图形文件格式.PNG格式是非失真性压缩的,允许使用类似于GIF格式的调色板技术,支持真彩色图像,并具备阿尔法通道(半透明)等特性.现在有很多人使用PNG格式于互联网及 ...