在实现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);

}

我们发现当字符串自己给自己赋值时,当目标字符串大于源字符串要拷贝的字符的个数时,程序就会出现错误,这里就涉及到了内存覆盖问题。

我们首先分析源字符串与目标字符串之间的关系:

    当源字符串给目标字符串赋值时,即从src给dest赋值时,情况二会出现问题。我们知道目标字符串和源字符串都是在操作一个字符串,在情况二中,当src给dest赋值直到dest的开始时,即不超过dest的偏移量时都没有什么问题,但是一旦超过偏移量,由于前面的赋值操作已经将字符串给改变了,然后再用改变过后的字符串再给dest赋值,这就导致了前面内容复制重复了,也就是发生内存覆盖了。在分析其他情况时我们可以发现程序都不会出现内存覆盖问题。
    要解决这个问题其实也不难,我们先明确要拷贝几个字符,找到要拷贝的最后一个字符,然后从后向前依次拷贝:

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语言之内存覆盖的更多相关文章

  1. C语言和内存

    1.程序的运行 对cpu来说,内存只是一个存放指令和数据的地方,具体的运算在cpu内完成. 1.寄存器(Register) 是CPU内部非常小.非常快速的存储部件,它的容量很有限,对于32位的CPU, ...

  2. 记一次难忘的排错debug经历(找了5天左右)(涉及内存覆盖)

    strcpy和memcpy都没有处理内存覆盖问题. 函数描述 The memcpy function copies count bytes of src to dest. If the source ...

  3. C语言中内存的申请函数

    C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等. alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且 ...

  4. JVM内存管理------JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  5. 不可或缺 Windows Native (9) - C 语言: 动态分配内存,链表,位域

    [源码下载] 不可或缺 Windows Native (9) - C 语言: 动态分配内存,链表,位域 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 动态分配内存 链 ...

  6. c语言之内存的申请malloc() 和释放free()

    c语言之内存的申请malloc() 和释放free() 1.如何使用 malloc 函数 malloc是一个函数,专门用来从堆上分配内存.使用malloc函数需要几个要求: 内存分配给谁?分配多大内存 ...

  7. C语言的内存管理

    C语言的内存管理 转载:http://blog.csdn.net/wind19/article/details/5964090   对于一个C语言程序而言,内存空间主要由五个部分组成代码段(.text ...

  8. (十一)C语言中内存堆和栈的区别

    在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念. 堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认 ...

  9. C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

    C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...

随机推荐

  1. Sqli-labs less 47

    Less-47 本关的sql语句为    $sql = "SELECT * FROM users ORDER BY '$id'"; 将id变为字符型,因此根据我们上述提到的知识,我 ...

  2. ubuntu修改ip、网关、dns等

    一.使用命令设置Ubuntu IP地址 1.修改配置文件blacklist.conf禁用IPV6 sudo vi /etc/modprobe.d/blacklist.conf 表示用vi编辑器(也可以 ...

  3. chrome 网络面板

    Chrome Timeline的指标说明:Blocked.Connect.Send.Wait.Receive Blocked time includes any pre-processing time ...

  4. 用于主题检测的临时日志(b42e98ba-eb4f-4099-a54c-7aee3f29c3dd - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

    这是一个未删除的临时日志.请手动删除它.(184c28c9-c88e-48fe-9713-6891e2d15044 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

  5. POJ 3255

    Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6605   Accepted: 2458 Descri ...

  6. 2013 ACM/ICPC Asia Regional Online —— Warmup

    1003 Rotation Lock Puzzle 找出每一圈中的最大值即可 代码如下: #include<iostream> #include<stdio.h> #inclu ...

  7. JS中的this好神奇,都把我弄晕了

    一.this的常见判断: 1.函数预编译过程 this —> window 2.全局作用域里 this —> window 3.call/apply 可以改变函数运行时this指向 4.o ...

  8. 矩阵快速幂 POJ 3735 Training little cats

    题目传送门 /* 题意:k次操作,g:i猫+1, e:i猫eat,s:swap 矩阵快速幂:写个转置矩阵,将k次操作写在第0行,定义A = {1,0, 0, 0...}除了第一个外其他是猫的初始值 自 ...

  9. 李洪强iOS开发之UICollectionView的使用

    想做如下的界面效果(纯代码) ------------------------------------------------------------------------------------ ...

  10. POJ2126——Prime Path(BFS)

    Prime Path DescriptionThe ministers of the cabinet were quite upset by the message from the Chief of ...