• 由memcpy内存越界引发的问题 && delete 和 delete []的真正区别


    今天遇到了一个问题,在程序运行到某处总会报访问到错误的地址的错误,而且每次报错的堆栈还都不一样,排查了一段时间,发现是memcpy这里出了错

            char *d = new char[data.size() * 4];
            memset(d, 0, data.size() * 4);
    
            memcpy(d,temp_content.c_str(), temp_content.size());

    这里乍一看没什么问题,但是如果这里data字符串为空而temp_content不为空的话,memcpy这样调用就出现了错误。

    虽然暂时不会报错,因为这里通过new char[0]申请到了一个内存地址的指针(这里虽然为0但至少应该申请到了1块),这样memset不会报错,即使memset(d, 0, 1000);大概率也不会报错,只要后面的这块连续的内存没被别人占用

    所以memcpy(d,temp_content.c_str(), temp_content.size());这种向未申请的内存中写数据也不会报错,但是这样的操作会破坏未申请内存的数据结构,当下一次别的操作申请内存时,申请到被破坏的内存,程序就会报错崩溃了(程序是不会关心你这个指针用的内存属不属于自己,只会关心你有没有用别人的内存!!!)

    最好用memcpy_s代替!

    delete 和 delete []的真正区别

    这个和上面的问题有一点关联度,就是malloc 和 new的时候需要指定申请内存的大小,为什么free和delete时不需要呢?

    先解释delete和delete[]的区别,他们同样都会释放指针所指向的内存空间,但如果指针类型不是基本数据结构时,delete只会调用第一个数组内的析构函数,其他的数组成员的析构函数都不会被调用!!!

    第二个问题的答案

    在学内存分配的问题的时候,malloc和calloc都要指定需要分配内存的大小,但是free的就不需要,我就纳闷free是咋知道从指针地址开始的多少长度是被分配了的?

    当时就想,在malloc或者calloc的时候,编译器应该把大小的数值放到哪个地方了,当free的时候就去找那个数值,释放掉数值大小的堆空间。

    但是到底放哪呢?

    前几天在网上一阵乱逛,说是现代编译器就是把大小的数值放在分配地址开始的之前位置,但是具体在之前多少位置呢?今天在vs的内存监视器里面看到了。

    测试代码如下:

    [cpp] 
    #include "stdlib.h" 
    #include "stdio.h" 
     
    #define Num 100 
     
    int main(void) 

        int i; 
        int *p=(int *)malloc(Num); 
        for (i=0;i<Num;i++) 
        { 
            *(p+i)=1;   //赋值为1只是为了看起来方便 
        } 
        free(p); 
     
        return 0; 

    其中p的地址为0x00393220
    接着打开vs2008的内存监视器窗口看:


    有一个地址为0x00393210的很可疑,因为0x64=100

    那么改一下看看:

    [cpp] 
    #define Num 50 
    再看内存监视器:


    看到*(0x00393210)=0x32;即0x32=50

    那应该就是把大小放这里了,就是说距离分配地址0x10之前的位置。

    从中可以看出为什么分配堆更号内存大小(当然它的主要方面还是“碎片”的产生)的一个小方面~~~

  • 相关阅读:
    MHA自动切换流程
    手写源码之 简单实现on emit off
    手写源码 -- bind,call,aplly
    多维数组转化为一维数组
    electron+vue中使用nodeJs的fs模块以及上传文件
    制作海报
    vue中引入播放器(百度播放器和腾讯云播放器)
    webpack配置
    webpack
    css样式
  • 原文地址:https://www.cnblogs.com/wangshaowei/p/10035185.html
Copyright © 2020-2023  润新知