C++ delete []p 数组指针,如何知道该数组大小的

本来只是一时兴起,想动手整整大学学的很渣的C++,可是一段小小的代码缺牵扯出一堆问题来,好有趣。

来看一段代码:

void main()
{
    char p[6];
    char *buf = new char[4];
    strcpy(buf,"012356789");//这里越界不会报错
    strcpy(p,"Hello"); //若此处越界立即报错

    cout<<p<<endl;
    cout<<buf<<endl;

    delete []buf;  //buf拷贝越界,这里释放数组报错
}

第一个问题:为什么数组指针buf在拷贝越界的时候(所指向的数组大小只有4,而拷贝进去的大小却是11),为何打印的时候也没有报错呢?

  这个问题百度还是很好找,cout<<标准输出,字符串数组指针,碰到‘\0‘才会认为字符串结束(这也是为什么我们<<buf就可以直接将整个字符串打印出来,buf不是指数组首地址吗?),越界拷贝虽然违规了,但是运行还是没有问题,

因为我们只是可以读取越界后的字符而已。

第二个问题:为什么我们delete []buf会报错?

  我们可以看到到指针buf指向的数组大小只有4个字节,但是如果只delete 这四个以分配好的字节空间应该也不会有问题啊,肯定有什么地方给扰乱了。

第三个问题:那编译器是怎么知道这个数组大小的?

  这个问题承接第二个问题,因为通过指针我们是没法知道它所指向的对象的大小的。

  根据Inside The C++ Object Model上所言,现在的编译器大多使用两种方法, 一种是cookie, 一个记录分配空间大小的内存小块绑定在分配内存的地址头部。二是使用表来对分配了的指针进行管理,每一个分配了空间的指针都在表中对应着分配空间的大小。

  在VC 上,是通过第一种方式记录的,即:VC对于数组的大小信息存放在:"数组首地址 - 4 * sizeof(int)"之中,我们可以添加以下代码:

cout<<"begin print size = "<< *reinterpret_cast<int*>(reinterpret_cast<char*>(buf) - 4 * sizeof(int))<<endl;

在这里你可以更改前面代码*buf指针所指向数组初始化时的大小,会发现这里都会与之相同,而不管strcpy拷贝的时候往数组地址边界后塞了多少东西。

那这样来看,编译器如果只根据cookie记录的数组大小去释放理应是不会报错的.

至于原因,我目前还不清楚,欢迎各位看官指点迷津.....

C++ delete []p 数组指针,如何知道该数组大小的,布布扣,bubuko.com

时间: 2024-11-18 15:11:19

C++ delete []p 数组指针,如何知道该数组大小的的相关文章

数组指针与二维数组的寻址

引例:已知如下程序 1 #include <stdio.h> 2 main() 3 { 4 int x[3][4] = {1,3,5,7,9,11,2,4,6,8,10,12} ; 5 int (*p)[4] = x, k = 1, m, n = 0; 6 for(m=0; m < 2; m++) 7 n += *(*(p+m)+k); 8 printf("%d\n",n); 9 } 试写出程序的输出值.(虽然我很讨厌做这种笔头功夫的题,我也坚信编程语言是在实践中练出

指针与数组--指针与二维数组2

指向一维数组的指针   char (*p)[10] ;指向一维数组的指针类型 typedef  char(*TYPE_P2ARRAY)[10]  ;   该指针可以指向数组 ,且使用起来效果节本相同,但指针与数组并不等价.{sizeof结果不同  , 且该指针还可以指向除此之外其他类型的数据. } #include <stdio.h> typedef int (*TP_PARRY1)[3] ; #define Uart_Printf printf void f1(void) { int a[2

5数组指针和引用:数组

数组 一维数组:数据类型  数组名 [常量表达式] 注意: 命名规则和变量名相同 数组后面一定是[],方括号内 是常量表达式 常量表达式表达元素的个数,即数组的长度 定义数组的常量表达式不能是变量 引用: 一维数组引用的一般形式:数组名[下标] 数组元素的下标起始值为0 初始化: 单个元素逐一赋值   a[10]=1;a[9]=100;...... 聚合方式赋值    int a[10]={1,2,.....10} ; int a[]={1,2,.....10}  ; int a[10]={1,

数组指针(二维数组的指针)

1 #include <iostream> 2 3 using namespace std; 4 5 6 int main() 7 { 8 int v[2][2]={{1,2},{3,4}}; 9 cout<<"v = "<<v<<endl; 10 cout<<"*v = "<<*v<<" &v = "<<&v<<endl;

指针数组 数组指针

指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针 数组指针:a pointer to an array,即指向数组的指针 还要注意的是他们用法的区别,下面举例说明. int* a[4]     指针数组 表示:数组a中的元素都为int型指针 元素表示:*a[i]   *(a[i])是一样的,因为[]优先级高于* int (*a)[4]   数组指针 表示:指向数组a的指针 元素表示:(*a)[i] 注意:在实际应用中,对于指针数组,我们经常这样使用: 1

数组指针、指针数组、函数指针、指针函数 -----笔记

1.数组的四种访问方式 定义数组 a[]; 指针 *p 指向数组a; (1) 利用数组的下表进行访问 a[i]; (2) 数组名+地址的偏移量i *(a+i) (3) 利用指针 p 进行下表访问 p[i] (4) 指针p + 地址的偏移量i *(p+i) 一维数组数组名:相当于一个单指针 2. 数组指针(指针)     指针数组(数组) 函数指针(指针)     指针函数(函数)    -------->只看后边两个字就能够区分是指针还是数组或函数 _______________________

第32课 数组指针和指针数组分析

1. 数组的类型 (1)C语言中的数组有自己特定的类型 (2)数组的类型由元素类型和数组大小共同决定.(如int array[5]类型为int[5]) 2. 定义数组类型 (1)C语言中通过typedef为数组类型重命名:typedef type(name)[size]; ①数组类型:如typedef int (AINT5)[5]; typedef float (AFLOAT10)[10]; ②数组定义:AINT5 iArray; AFLOAT10 fArray; 3. 数组指针 (1)数组指针

关于返回二维数组指针问题

所谓的二维数组指针,是指针的指针,指的就是二维数组在内存中的存储地址. 二维数组的地址与一维数组的地址的不同点是:它除了有元素地址外,还有标识各行起始位置的行首地址(称为行的首地址).行的首地址和行的首元素的地址具有相同的地址值,但是它们是两种不同的地址:若有定义int a[5][5]:则a[0][0]是a数组 首行首列元素(代表该元素的值).而&a[0][0]是首行首元素的地址.&&a[0][0]则是首行的首地址.从这个意义上讲,可以说行的首地址是一种二重地址,即指针的指针. 废

指针数组,数组指针、指针函数,函数指针

听到这几个名词不知道大家什么感受,反正我是一脸懵逼,不过我还是比较好学的,在老师的指导下,自己下去也钻研了一下,有一些自己的见解,我想在学习过程中也有童鞋遇到了相同的问题,希望我的总结能给你带来帮助. 首先我们想明确一下这几个概念,知道他们都表示什么,ok,请看: 函数指针:函数指针是指向函数的指针变量. 因而"函数指针"本身首先应是指针变量,只不过该指针变量指向函数.这正如用指针变量可指向整型变量.字符型.数组一样,这里是指向函数.如前所述,C在编译时,每一个函数都有一个入口地址,该

指针数组和数组指针的区别以及main函数

1.C语言中的数组有自己特定的类型 2.数组的类型有元素类型和数组大小共同决定 3.C语言中通过typedef为数组类型重命名 typedef type(name)[size]; 数组指针 1.数组指针用于指向一个数组 2.数组名是数组首元素的起始地址,但并不是数组的起始地址 3.通过将取地址符&作用于数组名可以得到数组的起始地址 4.可通过数组类型定义数组指针: ArrayType* pointer; 5.也可以直接定义:type (*pointer)[n];pointr为数组指针变量名,ty