• 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 ",str1);

          my_memcpy(str+2,str,4);//错误,拷贝出现了内存覆盖

         printf("str = %s ",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;

    }

     
  • 相关阅读:
    【NLP_Stanford课堂】最小编辑距离
    【NLP_Stanford课堂】句子切分
    【NLP_Stanford课堂】词形规范化
    【NLP_Stanford课堂】分词
    【NLP_Stanford课堂】正则表达式
    【Python自然语言处理】第一章学习笔记——搜索文本、计数统计和字符串链表
    【C++ Primer】详解C++和C中的float中的有效数字
    【C++ Primer】读书笔记_第一章
    【SQL Server 2012】按倒序存储“分组统计”结果的临时表到新建表
    Git学习
  • 原文地址:https://www.cnblogs.com/qingjiaowoxiaoxioashou/p/5689780.html
Copyright © 2020-2023  润新知