C/C++指针内存分配小细节
char *pc = NULL;
pc = new char[0];
pc[0] = '1';
相信初学者看见上面这段代码,都会觉得奇怪,new char[n]中的n指定给指针变量分配多少内存空间,而n=0时代表什么呢?
其实上面的程序编译、运行都是正确的。因为编译器识别到指定大小为0时,会自动为其分配1BYTE的内存空间。
尝试过的小伙伴会发现,给p[1]赋值也不会报错,原因留到后面讲*1。
但是,此时若想用delete [] p; 去释放内存空间就会报错,程序强制中断,因为编译器并没有真正意义上内指针变量分配内存,去释放肯定是不行的。
这就像对一个成功分配内存的指针变量,连续释放两次造成的错误,例子见后面*2。
好了,马上看一下成功分配内存的情况是怎么样的。
char *pc = NULL;
pc = new char[5];
pc[0] = '1';
这里的n=5,意味着给指针变量分配5个BYTE内存空间(因类型为char),当然不管是什么类型,指针变量本身均占4BYTE。
先来看上面遗留的第一个问题*1:此时不但可以给p[0]到p[4]赋值,还可以给后面的地址赋值,如p[5],p[10]等。
这就是C/C++完美之余的一个历史遗留缺陷,不进行越界检查。
导致编译没有任何问题,运行阶段有时一不小心也察觉不出,这就要求程序员养成良好的习惯:new后面必出现delete。
若我们在给p[5]或之后的地址赋过值,在运行到delete [] p;语句时,会报错,程序强制中断。错误原因如提示的信息:damage:after normal block。
这就是上面遗留的第二个问题*2:对同一个指针变量指向的内存释放两次,与释放一个没有成功分配内存或引用越界的指针变量类似,都是不允许的。
还有一个值得注意的地方:若new时n>0,delete后只是释放了原来内存地址中对应的值,指针变量仍然指向该内存地址,即:
仍可以赋值、取值进行运算,只是若没有重新赋值,取出的值为不确定值,换句话说就是,p成了传说中的野指针。
所以,这又是一个要求养成良好习惯的地方,看文章开头的地方,声明一个指针但未分配内存空间时,最好将其置为NULL。
这样做有两个好处:1、方便后面进行判断,if(!P){...}表示无内存分配,若当初没有将其置为NULL,则!p为真也代表不了什么;
2、在delete后,重新分配内存之前,将其置回为NULL,避免其成为野指针。
而对于malloc与free,情况类似,有兴趣的小伙伴可以尝试下。
刚开始学习这一块,有哪里不对的地方欢迎大家指出,谢谢!
C/C++指针内存分配小细节的更多相关文章
- 【C/C++学院】0828-数组与指针/内存分配/数据结构数组接口与封装
[送给在路上的程序猿] 对于一个开发人员而言,可以胜任系统中随意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并能够运用到系统中.由此简化系统的开发,是其架构生涯的第一步. ...
- C指针的一些小细节
1 int *c;*c=4-->int *c;int b;c=&b;*c=4; 在使用指针之前,一定要将其初始化,当然,如果是赋予一个地址,就相当于使用的同时就进行了初始化.
- c语言中较常见的由内存分配引起的错误_内存越界_内存未初始化_内存太小_结构体隐含指针
1.指针没有指向一块合法的内存 定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内浅显的例子就不举了,这里举几个比较隐蔽的例子. 1.1结构体成员指针未初始化 struct stude ...
- TCMalloc源码学习(三)(小块内存分配)
线程本地cache 线程本地cache对应的是类 ThreadCache,每一个thread一个实例,初始化代码在static函数CreateCacheIfNecessary中, 在该线程第一次申请内 ...
- C动态内存分配(C与指针实例)
主要初步介绍malloc.free.calloc.realloc的基本.日后会有更详细的内容. malloc.free分别用于动态内存分配和释放. malloc会从内存池里提取一块合适的内存(连续的) ...
- 【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析
. Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...
- C语言 内存分配 地址 指针 数组 参数 实例解析
. Android源码看的鸭梨大啊, 补一下C语言基础 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/detai ...
- <c和指针>学习笔记5动态内存分配和预处理器
1 动态内存 比如声明数组得时候,我们需要提前预估数组长度,分配大了浪费,少了就更不好操作了.从而引入动态分配,需要的时候再分配. (1)malloc和free void *malloc(size_t ...
- 漫步Facebook开源C++库Folly之string类设计(散列、字符串、向量、内存分配、位处理等,小部分是对现有标准库和Boost库功能上的补充,大部分都是基于性能的需求而“重新制造轮子”)
就在近日,Facebook宣布开源了内部使用的C++底层库,总称folly,包括散列.字符串.向量.内存分配.位处理等,以满足大规模高性能的需求. 这里是folly的github地址:https:// ...
随机推荐
- Github学习之路-小试牛刀,练习Git 的基本操作
一.下子windows客户端. Git 客户端下载地址:http://msysgit.github.io/ 二.打开Git Bash 命令行操作界面. 安装完成后,在开始菜单里找到“Git”-> ...
- C++ sort函数
(一)为什么要用c++标准库里的排序函数 Sort()函数是c++一种排序方法之一,学会了这种方法也打消我学习c++以来使用的冒泡排序和选择排序所带来的执行效率不高的问题!因为它使用的排序方法是类似于 ...
- beeline vs hive cli
近期,大数据开发环境升级为cloudera 5.3. 配套的hive版本升级为0.13.1.可以使用心仪已久的分析开窗函数了.但在使用的过程中发现一些问题,仅记于此. 1.在使用hive命令的时候,发 ...
- jquery 实现邮箱输入自动提示功能:(二)
上篇文章写到了一个不错的jquery实现邮箱输入自动提示功能,发现还有一个不错的自动提示插件: 先展示结果如图: html代码: <center> <h1>输入邮箱试试!< ...
- python中range函数和xrange函数有什么异同?
http://ciniao.me/article.php?id=17 简单来说,range生成的是一个列表,而xrange生成的是一个生成器,而生成器在数组很大的时候能够比range更节省空间
- AutoIT 实现Firefox上传文件
Firefox浏览器文件上传代码如下: ;upload file Func _UploadFile($file) AutoItSetOption("WinTitleMatchMode&quo ...
- git 添加文件
git 添加文件三步骤 git add filename git commit -m 'remarks' git push origin master
- css继承性和不继承的属性。
在CSS中并不是所有的属性都是能够继承的,因此在使用时一定要了解哪些是能够继承的哪些是不能够继承的.visibility和cursor能够被所有元素继承:letter-spacing,word-spa ...
- 08Spring_Spring和junit测试集成
第一步: 在项目导入 spring-test-3.2.0.RELEASE.jar 第二步: 编写测试类
- [py]编码 Unicode utf-8
什么是字符集 在介绍字符集之前,我们先了解下为什么要有字符集.我们在计算机屏幕上看到的是实体化的文字,而在计算机存储介质中存放的实际是二进制的比特流.那么在这两者之间的转换规则就需要一个统一的标准,否 ...