由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之前的位置。

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

原文地址:https://www.cnblogs.com/wangshaowei/p/10035185.html