嵌入式Linux系统编程 — 5.6 Linux系统申请堆内存

目录

1 内存概念

1.1 什么是堆内存

1.2 内存分布

2 malloc、free在堆上分配与释放内存

2.1 malloc函数

2.2 free函数

2.3 示例程序

注意事项:

3 calloc分配内存

3.1 calloc函数介绍

3.2 示例程序

4 分配对齐内存

4.1 函数介绍

4.2 示例程序


1 内存概念

1.1 什么是堆内存

堆内存(Heap Memory)是计算机程序中用于动态内存分配的内存区域。与栈内存(Stack Memory)不同,堆内存的分配和释放不是自动的,而是由程序员通过调用内存分配函数(如C语言中的 mallocfree)来控制的。

1.2 内存分布

  • 栈(Stack):用于存储局部变量和函数调用信息,向高地址增长。
  • 堆(Heap):用于动态内存分配,向低地址增长。
  • 全局/静态区(Global/Static Area):存储全局变量和静态变量,生命周期与程序相同。
  • 常量区(Constant Area):用于存储程序中的常量数据,这些数据在整个程序的生命周期内保持不变,并且在程序的多个地方可能被引用。C语言可以使用 const 关键字来定义常量。
  • 代码区(Code Area):存储程序的指令。
  • 其他:可能还包括文件缓冲区、环境变量等。

2 malloc、free在堆上分配与释放内存

2.1 malloc函数

Linux C 程序当中一般使用 malloc()函数为程序分配一段堆内存,而使用 free()函数来释放这段内存,先来看下 malloc()函数原型,如下所示:

#include <stdlib.h>

void *malloc(size_t size);
  • size: 堆上分配一块大小为 size 字节的内存区域。
  • 返回值: 返回指向这块内存的指针;如果分配失败(通常是由于内存不足),它会返回 NULL

2.2 free函数

free 用于释放之前通过 malloccalloc 或 realloc 等函数分配的内存。这块内存空间在函数执行完成后不会释放,它们的值是未知的,所以通常需要程序员对 malloc()分配的堆内存进行内存释放操作。通常使用 free()函数释放堆内存, free()函数原型如下所示:

#include <stdlib.h>

void free(void *ptr);
  • ptr: 指向需要被释放的堆内存对应的指针。
  • 返回值: 无返回值

2.3 示例程序

下面是一个简单的C语言程序示例,演示了如何使用 mallocfree 进行动态内存分配和释放:

#include <stdio.h>
#include <stdlib.h> // 包含malloc和free函数的头文件

int main() 
{
    int n; // 定义一个整数变量,用于存储数组的大小
    printf("Enter the size of the array you want to create: ");
    scanf("%d", &n); // 从用户那里获取数组的大小

    // 使用malloc动态分配一个整数数组的内存
    int *array = (int *)malloc(n * sizeof(int));
    if (array == NULL) {
        // 如果分配失败,打印错误信息并退出程序
        fprintf(stderr, "Error: Memory allocation failed!\n");
        return 1;
    }

    // 初始化数组
    for (int i = 0; i < n; i++) {
        array[i] = i * i; // 例如,将数组元素设置为其索引的平方
    }

    // 打印数组内容
    printf("Array elements:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");

    // 使用完数组后,使用free释放分配的内存
    free(array);

    // 再次打印数组内容,此时应该输出未定义的值
    printf("Attempt to print array after freeing memory:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", array[i]); // 此处访问已释放的内存,可能导致未定义行为
    }
    printf("\n");

    return 0;
}

程序通过 malloc 函数动态分配一个整数数组的内存,大小由用户输入决定,用 free 函数释放之前分配的内存。尝试再次打印数组内容,这将导致未定义行为,因为内存已经被释放。运行结果如下:

注意事项:

  • 释放内存后,不应该再访问该内存区域,否则可能导致程序崩溃或产生不可预测的结果。
  • 确保在使用完动态分配的内存后调用 free 函数,以避免内存泄漏。

3 calloc分配内存

3.1 calloc函数介绍

alloc 与 malloc 类似,但有一些关键的区别。calloc 用于分配足够存储一个指定数量的对象的内存块,并且将分配的内存初始化为0。这种分配对于需要从零开始的数组或数据结构非常有用。calloc 函数原型:

#include <stdlib.h>

void *calloc(size_t num, size_t size);
  • num:要分配的对象的数量。
  • size:每个对象的大小(以字节为单位)。
  • 返回值:如果内存分配成功,calloc 返回指向分配内存的指针,并且这块内存的所有字节都被初始化为零。如果内存分配失败,calloc 返回 NULL

3.2 示例程序

下面是 calloc 函数的示例程序,程序会动态分配一个整数数组的内存,并初始化所有元素为零,然后打印数组的内容,最后释放内存。

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int n; // 数组的大小
    printf("Enter the size of the array you want to create: ");
    scanf("%d", &n); // 从用户那里获取数组的大小

    // 使用calloc动态分配一个整数数组的内存,并初始化为零
    int *array = (int *)calloc(n, sizeof(int));
    if (array == NULL) {
        // 如果分配失败,打印错误信息并退出程序
        fprintf(stderr, "Error: Memory allocation failed!\n");
        return 1;
    }

    // 打印数组内容,此时所有元素都是0
    printf("Array elements (initialized to zero):\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");

    // 可以选择在这里修改数组的某些元素
    // 例如:array[0] = 1; // 将第一个元素设置为1

    // 使用完数组后,使用free释放分配的内存
    free(array);

    // 再次尝试访问数组内容,将会导致未定义行为
    // printf("Attempt to print array after freeing memory: %d\n", array[0]);

    return 0;
}

运行结果如下 

4 分配对齐内存

4.1 函数介绍

C 函数库中还提供了一系列在堆上分配对齐内存的函数,对齐内存在某些应用场合非常有必要,常用于分配对其内存的库函数有: posix_memalign()、 aligned_alloc()、 memalign()、valloc()、 pvalloc(),如果不需要特定的对齐,通常使用 malloc()calloc() 就足够了。它们的函数原型如下所示:

posix_memalign()函数:分配一块至少 size 大小的内存,并确保其地址是 alignment 的倍数。如果成功,返回0;如果失败,返回一个错误码。

#include <stdlib.h>

int posix_memalign(void **ptr, size_t alignment, size_t size);
  • ptr:指向一个 void* 的指针,函数将通过这个指针返回分配的内存的地址。
  • alignment:所需的内存对齐字节数,必须是2的幂,也必须是 sizeof(void*) 的倍数。
  • size:要分配的内存大小(以字节为单位)。
  • 功能:

aligned_alloc()函数:分配一块至少 size 大小的内存,并且返回的内存地址是 alignment 的倍数。如果分配成功,返回指向分配内存的指针;如果失败(如对齐要求无法满足),返回 NULL

#include <stdlib.h>

void *aligned_alloc(size_t alignment, size_t size);
  • alignment:内存对齐的字节数,必须是2的幂。
  • size:要分配的内存大小。

memalign()函数:与 posix_memalign 类似,分配一块至少 size 大小的内存,memalign()与 aligned_alloc()参数是一样的,它们之间的区别在于:对于参数 size 必须是参数 alignment
的整数倍这个限制条件, memalign()并没有这个限制条件。

#include <malloc.h>

void *memalign(size_t alignment, size_t size);
  • alignment:所需的内存对齐字节数。
  • size:要分配的内存大小。

valloc()函数:分配一块至少 size 大小的内存,并且地址是页面大小的整数倍。页面大小通常为4096字节。

#include <stdlib.h>

void *valloc(size_t size);
  • size:要分配的内存大小。

pvalloc()函数:分配足够大的内存,以确保至少有一个页面,并且返回的内存地址是页面大小的整数倍。分配的内存大小将是 size 的下一个页面大小的倍数。

#include <malloc.h

void *pvalloc(size_t size);
  • size:要分配的内存大小,必须是非负整数,并且足够大,以确保分配的内存至少有一个页面。

4.2 示例程序

以下是使用 posix_memalign()aligned_alloc()memalign()valloc()pvalloc() 函数的示例程序。程序使用这些函数来分配内存,并打印出分配的内存地址,以展示内存对齐的效果。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <malloc.h>

int main() 
{
    void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
    size_t size = 1024; // 分配大小为1KB的内存
    size_t alignment = 64; // 指定内存对齐到64字节边界

    // 使用posix_memalign分配内存
    if (posix_memalign(&ptr1, alignment, size) != 0) {
        perror("posix_memalign failed");
        return 1;
    }
    printf("Memory allocated by posix_memalign: %p\n", ptr1);

    // 使用aligned_alloc分配内存
    ptr2 = aligned_alloc(alignment, size);
    if (ptr2 == NULL) {
        perror("aligned_alloc failed");
        return 1;
    }
    printf("Memory allocated by aligned_alloc: %p\n", ptr2);

    // 使用memalign分配内存(GNU扩展)
    ptr3 = memalign(alignment, size);
    if (ptr3 == NULL) {
        perror("memalign failed");
        return 1;
    }
    printf("Memory allocated by memalign: %p\n", ptr3);

    // 使用valloc分配内存
    ptr4 = valloc(size);
    if (ptr4 == NULL) {
        perror("valloc failed");
        return 1;
    }
    printf("Memory allocated by valloc: %p\n", ptr4);

    // 使用pvalloc分配内存
    ptr5 = pvalloc(size);
    if (ptr5 == NULL) {
        perror("pvalloc failed");
        return 1;
    }
    printf("Memory allocated by pvalloc: %p\n", ptr5);

    // 释放分配的内存
    free(ptr1);
    free(ptr2);
    free(ptr3); // 注意:memalign分配的内存需要用free释放
    free(ptr4);
    free(ptr5); // 注意:pvalloc分配的内存需要用free释放

    return 0;
}

运行结果如下:

运行结果可以看到每个函数分配的内存地址,地址显示了不同函数分配内存时对齐方式的差异。下面是对每个函数分配结果的分析:

  • posix_memalign:分配的内存地址是 0x5574280be040,地址的最低几位数字(040)显示了内存对齐的情况,地址是按照16字节对齐的(因为040是16的倍数)。
  • aligned_alloc:分配的内存地址是 0x5574280beb80,地址的最低几位数字(b80)表明内存也是按照16字节对齐的。
  • memalign:分配的内存地址是 0x5574280bf000,地址以 000 结尾,表明内存是按照页面大小(通常是4096字节或4KB)对齐的。
  • valloc:分配的内存地址是 0x5574280c0000,地址以 0000 结尾,进一步证实了 valloc 函数分配的内存确实是按照页面大小对齐的。
  • pvalloc:分配的内存地址是 0x5574280c1000。同样以 000 结尾,表明这也是页面大小对齐的内存。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/761633.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【QT】输入类控件

目录 Line Edit 核心属性 核心信号 正则表达式 示例&#xff1a;使用正则表达式验证输入框内容 示例&#xff1a;切换输入框密码模式下的显示状态 Text Edit 核心属性 核心信号 示例&#xff1a;获取多行输入框的内容同步显示到label 示例&#xff1a;获取文本的选…

Navcat Premium17破解安装及数据库连接教程

一、前言 Navicat Premium 是一套数据库开发工具&#xff0c;是一个可多重连接数据库的管理工具。Navicat Premium让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 数据库。目前17已经支持了很久都没有支持的Redis数据库了。…

【办公软件使用分享—Word篇】实用技巧 一学就会 沈阳电脑办公软件基础培训

在平时的工作学习中&#xff0c;Word真真是让很多人头疼的一件事&#xff0c;今天给大家分享20个案例&#xff0c;感受下Word真正的力量&#xff01; 1.插入自动目录 没有目录的文档不是一份合格的文档&#xff0c;很多人认为在Word里插入目录是一件很麻烦的事&#xff0c;其…

[leetcode]max-consecutive-ones 最大连续1的个数

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int findMaxConsecutiveOnes(vector<int>& nums) {int maxCount 0, count 0;int n nums.size();for (int i 0; i < n; i) {if (nums[i] 1) {count;maxCount max(maxCount, count);} else…

4面体空间含支链4点结构种类与占比

在30个点的4面体内取4个点&#xff0c;要求这4个点可以是直链或支链&#xff0c; 共有188个结构符合要求&#xff0c;36个直链结构每个有4个。 这种支链结构每个有10个 这种支链结构每个有1个 旋转对称关系为 A B C D 0 120 240 0 120 240 0 120 240 0 120 240…

Steam商店报错、进不去 Steam105错误代码的处理方法

逛Steam商店现在已然成为大部分游戏玩家每日必做的事情之一&#xff0c;玩家们在商店浏览、购买并享受各种类型的游戏和应用&#xff0c;找到适合自己的一款&#xff0c;最近steam夏促活动正在进行&#xff0c;很多玩家都前往Steam商店查看各种低价游戏&#xff0c;但是很多玩家…

第2章-Python编程基础

#本章目标 1&#xff0c;了解什么是计算机程序 2&#xff0c;了解什么是编程语言 3&#xff0c;了解编程语言的分类 4&#xff0c;了解静态语言与脚本语言的区别 5&#xff0c;掌握IPO程序编写方法 6&#xff0c;熟练应用输出函数print与输入函数input 7&#xff0c;掌握Python…

泛型的使用(<T>)

文章目录 前言一、泛型是什么&#xff1f;二、泛型的使用 1.定义泛型类2.泛型的常规用法总结 前言 强制类型转换存在一定隐患&#xff0c;如数据丢失、内存溢出、运行时错误、程序逻辑错误等。所以提供了泛型机制&#xff0c;使程序员可以定义安全的数据类型进行操作。通俗的理…

【postgresql】 基础知识学习

PostgreSQL是一个高度可扩展的开源对象关系型数据库管理系统&#xff08;ORDBMS&#xff09;&#xff0c;它以其强大的功能、灵活性和可靠性而闻名。 官网地址&#xff1a;https://www.postgresql.org/ 中文社区&#xff1a;文档目录/Document Index: 世界上功能最强大的开源…

GP37-S-N、GP37-S-E、GP37-S-R比例电磁铁驱动放大器

比例阀用电磁铁EP45-C、EP37-E、EP45-G、EP45-N、GP37-3-A、GP37-S-N、GP37-S-E、GP37-S-R在直流12V/24V的电液比例控制系统中与BEUEC比例控制放大器配套使用&#xff0c;共同作用于比例阀的控制。电磁铁输出力通过负载弹簧转换成位移&#xff0c;实现电流-力-位移线性转换&…

嵌入式问题分析思路

BUG解决总体思路: 1.1 定位bug范围及性质 要有效解决问题&#xff0c;首先要缩小范围&#xff0c;集中关注最近的代码变化。这有助于迅速定位可能引入问题的部分&#xff0c;避免无谓的时间浪费。检查最近的代码提交记录和修改日志&#xff0c;找出可能影响现有功能的变更。然…

减肥期间三餐饮食搭配

减肥期间三餐饮食搭配 早起洗漱后早餐前:一杯温水大口喝下,清洁肠道!!! 减肥期间早餐搭配 早餐9点前完成✅ ❤必须喝(纯牛奶、无糖豆浆、无糖酸奶、黑咖啡都可以,四选一) ❤必须吃1~2个鸡蛋 (蒸,煮,煎,炒都可以) ❤必须吃主食 (红薯、玉米、南瓜、紫薯、山药…

基于单片机的 LED 照明灯智能调光系统设计

摘  要&#xff1a; 社会经济的不断发展&#xff0c;推动了智能化生活的进程&#xff0c;智能调光技术开始广泛应用在生活中&#xff0c;人们也逐渐提高了灯光亮灯率等的要求。基于此&#xff0c;笔者主要设计了基于单片机的 LED 照明灯智能调光系统&#xff0c;希望能够为相关…

小程序的运行机制、更新机制、生命周期介绍保姆级教程全解

一、小程序运行机制 1. 小程序冷启动 小程序启动可以分为两种情况&#xff0c;一种是冷启动&#xff0c;一种是热启动- 冷启动&#xff1a;如果用户首次打开&#xff0c;或小程序销毁后被用户再次打开&#xff0c;此时小程序需要重新加载启动- 热启动&#xff1a;如果用户已经打…

植物大战僵尸杂交版手机下载与安装全攻略

植物大战僵尸杂交版是一款深受玩家喜爱的策略冒险游戏&#xff0c;以其丰富的植物种类、多样的关卡设计和趣味的玩法著称。本文将为您提供详细的下载与安装教程&#xff0c;帮助您快速上手&#xff0c;享受游戏带来的乐趣。 游戏简介 植物大战僵尸杂交版在传统玩法的基础上&a…

使用React复刻ThreeJS官网示例——keyframes动画

最近在看three.js相关的东西&#xff0c;想着学习一下threejs给的examples。源码是用html结合js写的&#xff0c;恰好最近也在学习react&#xff0c;就用react框架学习一下。 本文参考的是threeJs给的第一个示例 three.js examples (threejs.org) 一、下载threeJS源码 通常我们…

视频监控业务平台LntonCVS国标视频综合管理平台功能及技术优势

随着安防行业的快速进步&#xff0c;传统的视频监控平台正在与先进的技术和互联网技术融合&#xff0c;包括5G通信、GIS、大数据、云计算、边缘计算、AI识别、智能分析和视频直播等。这些技术的整合形成了综合性视频监控管理平台&#xff0c;具备集中管理、多级联网共享、互联互…

中霖教育怎么样?税务师通过率高吗?

中霖教育怎么样?税务师通过率高吗? 我们在税务师考试培训方面有着不错的成绩&#xff0c;这都是老师与学员共同努力的结果。 采用小班教学模式&#xff0c;确保每位学员都能得到足够的关注和指导&#xff0c;在学习过程中针对学员的薄弱环节进行专项突破。 因为大部分学员…

Soul探索未来智能互动模式,人机交互重塑社交元宇宙体验

在当今快速发展的科技领域中,人机交互已成为一个备受关注的话题。随着人工智能和机器学习技术的不断进步,人们与计算机和智能设备之间的互动方式正在发生翻天覆地的变化。这种交互不止局限于键盘和鼠标,更涵盖了语音识别、手势控制、虚拟现实等多种形式。人机交互的创新不仅提高…

什么样的网工才是有前途的?

最近整个就业市场的变化&#xff0c;搞得人心惶惶。 可能很多朋友都在思考这样一个问题&#xff1a;现在做网工还有前途吗&#xff1f;什么样的网工才是有前途的&#xff1f;考HCIE认证还来得及吗&#xff1f; 作为网络工程师&#xff0c;该如何确保自己的职业发展方向正确&a…