热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++中的malloc函数详解

malloc是C语言中的一个标准库函数,全称为memoryallocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过malloc动态分配内存。

malloc 的全称是 memory allocation,中文译为动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存,且分配的大小就是程序要求的大小。

函数定义

malloc 的函数原型为:void *malloc(size_t size); 其作用是在内存的动态存储区中分配一个长度为 size 的连续空间。此函数的返回值是分配区域的起始地址,即一个指针,指向该分配域的开头位置。

如果分配成功,则返回指向被分配内存的指针(该存储区中的初始值不确定),否则返回空指针 NULL。当内存不再使用时,应使用 free() 函数将内存块释放。函数返回的指针需要适当对齐,以便可以用于任何数据对象。

早期版本的 malloc 返回 char 类型的指针,但新的 ANSI C 标准规定,该函数返回 void 类型的指针。因此,在使用时可能需要进行类型转换。malloc 能向系统申请分配一个长度为 num_bytes(或 size)个字节的内存块。通常,malloc 需要与 free 函数配对使用,以确保动态分配的内存能够正确释放。

工作机制

malloc 函数的核心机制在于维护一个空闲链表,该链表将所有可用的内存块连接起来。当调用 malloc 函数时,它会沿着链表寻找一个足够大的内存块来满足用户的请求。找到合适的内存块后,将其一分为二:一块与用户请求的大小相等,另一块则是剩余的部分。然后,将分配给用户的内存块返回给用户,并将剩余的内存块(如果有的话)重新放回链表中。调用 free 函数时,它会将用户释放的内存块重新连接到空闲链表上。

随着时间的推移,空闲链表可能会被分割成许多小的内存片段。如果用户请求一个较大的内存片段,而空闲链表中没有足够的连续内存块,malloc 会尝试将相邻的小内存片段合并成较大的内存块。如果仍然无法找到合适的内存块,malloc 将返回 NULL 指针。因此,在调用 malloc 动态申请内存时,必须检查其返回值是否为 NULL。

在 Linux 系统中,glibc 库通过 brk() 和 mmap() 系统调用来实现 malloc。当释放内存时,glibc 会尝试整合相邻的内存碎片,以提高内存利用率。

与 new 的区别

从本质上讲,malloc 是 C 语言标准库中的一个函数,而 new 是 C++ 语言中的关键字。malloc 需要包含头文件 stdlib.h,而 new 不需要包含任何头文件。C++ 编译器可以直接将 new 编译为目标代码,并插入相应的构造函数。

在使用上,malloc 和 new 有以下主要区别:

  • new 返回指定类型的指针,并且可以自动计算所需内存的大小。而 malloc 需要手动计算字节数,并在返回后强制转换为实际类型的指针。
  • malloc 只负责分配内存,不会对内存进行初始化,因此新分配的内存中的值是随机的。而 new 除了分配内存外,还会调用对象的构造函数,对内存进行初始化。
  • 通过 malloc 或 new 分配的内存,在其他操作上保持一致,但在释放内存时,malloc 使用 free 函数,而 new 使用 delete 运算符。

示例代码

以下是一个简单的示例,演示如何使用 malloc 函数分配和释放内存:

#include 
#include 

int main() {
    char *p;
    
    p = (char *)malloc(100);
    if (p) {
        printf("Memory Allocated at: %p\n", p);
    } else {
        printf("Not Enough Memory!\n");
    }
    free(p);
    return 0;
}

推荐阅读
  • NX二次开发:UFUN点收集器UF_UI_select_point_collection详解
    本文介绍了如何在NX中使用UFUN库进行点收集器的二次开发,包括必要的头文件包含、初始化和选择点集合的具体实现。 ... [详细]
  • 蒜头君的倒水问题(矩阵快速幂优化)
    蒜头君将两杯热水分别倒入两个杯子中,每杯水的初始量分别为a毫升和b毫升。为了使水冷却,蒜头君采用了一种特殊的方式,即每次将第一杯中的x%的水倒入第二杯,同时将第二杯中的y%的水倒入第一杯。这种操作会重复进行k次,最终求出两杯水中各自的水量。 ... [详细]
  • 本文介绍了Java编程语言的基础知识,包括其历史背景、主要特性以及如何安装和配置JDK。此外,还详细讲解了如何编写和运行第一个Java程序,并简要介绍了Eclipse集成开发环境的安装和使用。 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • 经过一年的思考,我发现自己对开发的兴趣并不浓厚,而对算法研究则更加热衷。本文将探讨开发与算法之间的本质差异,并分享我的未来学习计划。 ... [详细]
  • 小程序的授权和登陆
    小程序的授权和登陆 ... [详细]
  • 使用 Git Rebase -i 合并多个提交
    在开发过程中,频繁的小改动往往会生成多个提交记录。为了保持代码仓库的整洁,我们可以使用 git rebase -i 命令将多个提交合并成一个。 ... [详细]
  • Manacher算法详解:寻找最长回文子串
    本文将详细介绍Manacher算法,该算法用于高效地找到字符串中的最长回文子串。通过在字符间插入特殊符号,Manacher算法能够同时处理奇数和偶数长度的回文子串问题。 ... [详细]
  • 本文介绍了多种开源数据库及其核心数据结构和算法,包括MySQL的B+树、MVCC和WAL,MongoDB的tokuDB和cola,boltDB的追加仅树和mmap,levelDB的LSM树,以及内存缓存中的一致性哈希。 ... [详细]
  • Python多线程详解与示例
    本文介绍了Python中的多线程编程,包括僵尸进程和孤儿进程的概念,并提供了具体的代码示例。同时,详细解释了0号进程和1号进程在系统中的作用。 ... [详细]
  • 本文详细介绍了Linux系统中用于管理IPC(Inter-Process Communication)资源的两个重要命令:ipcs和ipcrm。通过这些命令,用户可以查看和删除系统中的消息队列、共享内存和信号量。 ... [详细]
  • A*算法在AI路径规划中的应用
    路径规划算法用于在地图上找到从起点到终点的最佳路径,特别是在存在障碍物的情况下。A*算法是一种高效且广泛使用的路径规划算法,适用于静态和动态环境。 ... [详细]
  • 解决SQL Server数据库sa登录名无法连接的问题
    在安装SQL Server数据库后,使用Windows身份验证成功,但使用SQL Server身份验证时遇到问题。本文将介绍如何通过设置sa登录名的密码、启用登录名状态以及开启TCP协议来解决这一问题。 ... [详细]
  • MySQL 数据库连接方法
    本文介绍了如何使用 MySQL 命令行工具连接到指定的数据库。 ... [详细]
  • 如何解决8080端口被占用问题
    本文介绍了如何通过命令行和任务管理器查找并终止占用8080端口的进程,以确保该端口能够正常使用。 ... [详细]
author-avatar
起薪d这帖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有