博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++中的内存重叠问题
阅读量:5242 次
发布时间:2019-06-14

本文共 2822 字,大约阅读时间需要 9 分钟。

  • 内存重叠,直到做到一个笔试题才知道了什么是内存重叠。先上题目吧,是一个淘宝的笔试题,当时有点懵,不知道这个名词是啥子意思。
  • 题目:补充下面函数代码:
    如果两段内存重叠,用memcpy函数可能会导致行为未定义。 而memmove函数能够避免这种问题,下面是一种实现方式,请补充代码。
    • #include 
      using namespace std;void* memmove(void* str1,const void* str2,size_t n){ char* pStr1= (char*) str1; const char* pStr2=(const char*)str2; if ( ) { for(size_t i=0;i!=n;++i){ *(pStr1++)=*(pStr2++); } } else{ pStr1+=n-1; pStr2+=n-1; for(size_t i=0;i!=n;++i){ *(pStr1--)=*(pStr2--); } } return ( );}在上面的两个括号中插入对应的内容答案:pstr1

      在这里我理解的内存重叠大致上应该是在strcpy以及memcpy等内存拷贝函数出现的问题。strcpy函数内存重叠可能会使程序崩溃,这里我先讲一个比较简单的例子来看一下。

    • #include 
      #include
      #include
      int main(){ char *p = NULL; p = (char *)malloc(10); memcpy(p,"1234679",strlen("1246789")); printf("before p = %s/n", p); strcpy(p+1,p);//这重叠了 printf("after p = %s/n", p); free(p);}

       上面的这个例子中发生了内存重叠问题,这就导致了拷贝发生了异常,不会拷贝一样的数据。我跑这个代码的时候居然没有报错,程序也没炸,我也就有点好奇了。按理来memcpy,strcpy这两个函数没有对内存重叠进行处理。使用这两个函数的时候只有程序员自己保证源地址与目标地址内存不重叠。所以当会发生内存重叠的时候最好使用memmov函数进行内存拷贝。

      自己查了一些资料,原来memcpy有一个长度参数,只拷贝cnt个字节就结束了,所以会得到正确的结果,但是strcpy函数知道拷贝到\0这个标志符才会结束,所以就会导致程序崩溃了。

  •   memcpy和memmov函数原型和区别
    •   1.memmove

      函数原型:void *memmove(void *dest, const void *source, size_t count)

      返回值说明:返回指向dest的void *指针

      参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数

      函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。

    •   2.memcpy

      函数原型:void *memcpy(void *dest, const void *source, size_t count);

      返回值说明:返回指向dest的void *指针

      函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

  •   实现一个memmov函数
    •   
      #include 
      #include
      using namespace std;void *memmove(void * dst, const void *src, size_t count){ //特殊情况错误处理 if (src == NULL || dst == NULL) return NULL; unsigned char *pdst = (unsigned char *)dst; const unsigned char *psrc = (const unsigned char *)src; //判断内存是否重叠 bool flag1 = (pdst >= psrc && pdst < psrc + count); bool flag2 = (psrc >= pdst && psrc < pdst + count); //上面两个标志其中有一个成立,保证内存并不是重叠的,与拷贝的长度有关 if (flag1 || flag2){
      //内存重叠 //倒序拷贝 while (count){ *(pdst + count - 1) = *(psrc + count - 1); count--; } } else{
      //不重叠 while (count--){ *pdst = *psrc; pdst++; psrc++; } } return dst;}int main(){ //内存重叠的情况 char str[] = "hello world"; memmove(str + 3, str, 8); cout<<"memmove result is :"<
      <

       

      实现思路就是要去判断是否内存重叠,重叠的话就倒序的拷贝,非重叠的话就从前往后拷贝就行了。这个例子也很好的解释了前面的那个题目的情况。其实前面的那个情况还可以用一个图片来解释。
    • 这张图片就是这两种情况的实现。

转载于:https://www.cnblogs.com/Kobe10/p/6023177.html

你可能感兴趣的文章
Hibernate-缓存
查看>>
【BZOJ4516】生成魔咒(后缀自动机)
查看>>
提高PHP性能的10条建议
查看>>
svn“Previous operation has not finished; run 'cleanup' if it was interrupted“报错的解决方法...
查看>>
熟用TableView
查看>>
Java大数——a^b + b^a
查看>>
poj 3164 最小树形图(朱刘算法)
查看>>
百度贴吧图片抓取工具
查看>>
服务器内存泄露 , 重启后恢复问题解决方案
查看>>
ajax post 传参
查看>>
2.1命令行和JSON的配置「深入浅出ASP.NET Core系列」
查看>>
android一些细节问题
查看>>
KDESVN中commit时出现containing working copy admin area is missing错误提示
查看>>
利用AOP写2PC框架(二)
查看>>
【动态规划】skiing
查看>>
java定时器的使用(Timer)
查看>>
Android实现静默安装与卸载
查看>>
ef codefirst VS里修改数据表结构后更新到数据库
查看>>
boost 同步定时器
查看>>
[ROS] Chinese MOOC || Chapter-4.4 Action
查看>>