在堆上分配内存:malloc和free

一般情况下,C程序使用malloc函数族在堆上分配和释放内存。较之brk和sbrk,这些函数具备不少优点:

属于C语言标准的一部分

更易于在多线程程序中使用

接口简单,允许分配小块内存

允许随意释放内存块,它们被维护于一张空闲内存列表中,在后续内存分配调用时循环使用

malloc函数在堆上分配参数size字节大小的内存,并返回指向新分配内存起始位置处的指针,其所分配的内存未经初始化。

#include <stdlib.h>
void *malloc(size_t size); /* Returns pointer to allocated memory on sucess, or NULL on error */

由于malloc的返回类型为void*,因而可以将其付赋给任意类型的C指针。malloc返回内存块所采用的的字节对齐方式,总是适宜于高效访问任何类型的C语言数据结构。在大多数硬件架构上,这意味着malloc是基于8字节或16字节边界来分配内存的。

SUSv3规定:调用malloc(0)要么返回NULL,要么是一小块可以(并且应该)用free释放的内存。Linux的malloc(0)遵循的是后者。

如果无法再分配内存(或许是因为已经达到了program break所能达到的地址上限),则malloc返回NULL,并设置errno以返回错误信息。

虽然分配内存失败的可能性很小,但所有对malloc以及后续提及的相关函数的调用都应对返回值进行错误检查。

free函数释放ptr参数所指向的内存块,该参数应该是之前由malloc,或者后续描述的其他堆内存分配函数之一所返回的地址。

#include <stdlib.h>
void free(void *ptr);

一般情况下,free并不降低program break的位置,而是将这块内存填加到空闲内存列表中,供后续的malloc函数循环使用。这么做是出于以下几个原因。

被释放的内存块通常会位于堆的中间,而非堆的顶部,因而降低program break是不可能的。

它最大限度地减少了程序必须执行的sbrk调用次数。

在大多数情况下,降低program break的位置不会对那些分配大量内存的程序有多少帮助,因为它们通常倾向于持有已经分配内存或是反复释放和重新分配内存,而非释放所有内存后再持续运行一段时间。

如果传给free的是一个空指针,那么函数将什么都不做。(换句话说,给free传入一个空指针并不是错误代码。)

在调用free后对参数ptr的任何使用,例如将其再次传递给free,将产生错误,并可能导致不可预知的结果。

Unix系统编程()在堆上分配内存的更多相关文章

  1. Java中对象并不是都在堆上分配内存的

    转(https://blog.51cto.com/13906751/2153924) 前段时间,给星球的球友们专门码了一篇文章<深入分析Java的编译原理>,其中深入的介绍了Java中的j ...

  2. 《Linux/UNIX系统编程手册》读书笔记

    2018-1-30 一.UNIX.C语言以及Linux的历史回顾 1. UNIX简史.C语言的诞生 1969年,贝尔实验室的Ken Thompson首次实现了UNIX系统. 1973年,C语言步入成熟 ...

  3. Unix系统编程()brk,sbrk

    在堆上分配内存 进程可以通过增加堆的大小来分配内存,所谓堆是一段长度可变的连续虚拟内存,始于进程的未初始化数据段末尾,随着内存的分配和释放而增减.通常将堆的当前内存边界称为"program ...

  4. Java中的对象都是在堆上分配的吗?

    作者:LittleMagic https://www.jianshu.com/p/8377e09971b8 为了防止歧义,可以换个说法: Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定 ...

  5. 《Linux/Unix系统编程手册》读书笔记4

    <Linux/Unix系统编程手册>读书笔记 目录 第7章: 内存分配 通过增加堆的大小分配内存,通过提升program break位置的高度来分配内存. 基本学过C语言的都用过mallo ...

  6. 《Linux/Unix系统编程手册》读书笔记3

    <Linux/Unix系统编程手册>读书笔记 目录 第6章 这章讲进程.虚拟内存和环境变量等. 进程是一个可执行程序的实例.一个程序可以创建很多进程. 进程是由内核定义的抽象实体,内核为此 ...

  7. 《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

    <Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候 ...

  8. 《Linux/Unix系统编程手册》读书笔记5

    <Linux/Unix系统编程手册>读书笔记 目录 第8章 本章讲了用户和组,还有记录用户的密码文件/etc/passwd,shadow密码文件/etc/shadow还有组文件/etc/g ...

  9. 《Linux/Unix系统编程手册》读书笔记1

    <Linux/Unix系统编程手册>读书笔记 目录 最近这一个月在看<Linux/Unix系统编程手册>,在学习关于Linux的系统编程.之前学习Linux的时候就打算写关于L ...

随机推荐

  1. html input type=date 赋值问题 必须yyyy-mm-dd格式

    type=date ,日期类型默认格式是yyyy-mm-dd 因此必须给该控件赋值yyyy-mm-dd格式的数据 错误的赋值 <input type="date" id=&q ...

  2. Code a simple telnet client using sockets in python

    测试端口是否开放的python脚本 原文: https://www.binarytides.com/code-telnet-client-sockets-python/ 配置: 120.79.14.8 ...

  3. (剑指Offer)面试题43:n个骰子的点数

    题目: 把n个骰子仍在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率. 思路: s可能出现的值的范围为:n--6*n 1.全排列 回溯法枚举n个骰子(6面)的全排列,然 ...

  4. Google Maps API v2密钥申请以及实现地图定位导航

    注意新建项目之前需要安装 google play  services 然后导入 通过上图方法导入sdk包下面的一个包: \adt-bundle-windows-x86\sdk\extras\googl ...

  5. C#基础视频教程3.2 常见控件类型和使用方法

    这一部分我们介绍如何使用第三方的控件,我们前面一节介绍了使用微软提供的官方控件,比较中规中矩,而且也不用担心稳定性.但是很多时候我们还是会希望用第三方的控件让自己的软件更美观,更独特. 就单纯的按钮, ...

  6. C#基础视频教程1 背景知识和安装配置

    安装过程比较简单,用虚拟光驱工具加载ISO文件,然后打开EXE安装即可,主要使用VS2013(VS2015也出来了,但是用的还不算多)     建议设置为深色(比较容易看清)   建议显示行号,不要自 ...

  7. 算法笔记_142:无向图的欧拉回路求解(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 John's trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8 ...

  8. vue 表单 验证 async-validator

    1.使用插件async-validator async-validator 地址:https://github.com/yiminghe/async-validator 2.示例(vue+elemen ...

  9. No implementation found for long com.baidu.platform.comjni.map.commonmemcache.JNICommonMemCache.Create()

    3-21 10:14:20.833 2892-2892/? E/art: No implementation found for long com.baidu.platform.comjni.map. ...

  10. Linux下查看磁盘挂载的三种方法

    Linux下查看磁盘挂载的三种方法 2009-06-05 23:17 好久没有更新日志了,呵呵.不是没有要写的东东.实在抽不出时间来写,要准备公司的考试呢,C++考试.已经有七个月没有写C++代码了, ...