嵌入式C语言面试相关知识——内存管理(不定期更新)

一、博客声明

  又是一年一度的秋招,怎么能只刷笔试题目呢,面试题目也得看,想当好厂的牛马其实也不容易呀O(∩_∩)O。注意:这篇博客大部分是来自网上的资源,通过自问或者他问,然后寻找答案,为了加深印象,总结和抄一遍。并且会不定期更新这个方面的内容。


二、自问题目

1、嵌入式系统的内存布局是怎么样的?

  嵌入式系统中的内存布局分为5个部分:*栈(Stack)、堆(Heap)、BBS段(Block Started by Symbol)、 数据段(Data Segment)、 代码段(Text Segment) 。 其描述可以看下面这幅图片。
在这里插入图片描述

  • 栈(Stack): 用于函数调用时局部变量和函数调用信息,从高地址向低地址增长。栈的大小和生命周期由编译器在编译时确定,通常在程序启动时就分配好了。

  • 堆(Heap): 用于动态内存分配,从低地址向高地址增长。在程序运行时,需要通过函数如malloc()free() 来动态分配和释放内存。

  • BSS段(Block Started by Symbol): 用于存放未初始化的全局变量和静态变量。在程序运行前会将这些变量初始化位0或者空指针。

  • 数据段(Data Segment): 存放已经初始化的全局变量和静态变量,在程序运行前就已经分配好了内存空间。

  • 代码段(Text Segment): 存放程序的机器指令,通常是只读的。通常包括程序的执行代码,如函数、循环、条件语句等。

2、动态内存分配在嵌入式系统中的使用有什么注意事项?

  动态内存分配需要注意四个问题,分别是内存碎片、内存泄漏、实时性和资源受限。

  • 内存碎片: 频繁的动态内存分配和释放可能导致内存碎片,影响系统稳定性。
  • 内存泄漏: 未释放的内存会导致内存泄漏,逐渐耗尽可用内存。
  • 实时性: 动态内存分配的时间开销可能不确定,影响系统的实时性能。
  • 资源受限: 嵌入式系统通常内存资源有限,应该尽量避免频繁的使用动态内存分配。

3、什么是内存碎片,如何减少内存碎片?

  • 内存碎片: 内存碎片分为了内部碎片和外部碎片:

    • **内部碎片: ** 分配的内存块比实际需要的内存大,未使用的部分称为内部碎片。
    • **外部碎片: ** 多个小的内存块之间存在未使用的空间,无法被利用。
  • 减少内存碎片的方法:

    • 使用固定大小的内存块: 分配固定大小的内存块,避免大小不一的内存分配。
    • 内存池: 使用内存池进行内存分配和释放,减少碎片。
    • 紧凑算法: 在适当的时候进行内存紧凑,合并小块内存。

4、什么是内存池,有什么特点优势,工作原理是什么?

  • 内存池: 是一种管理内存分配和释放的技术,其核心思想就是预先分配一定数量的内存块,然后在程序运行期间重复使用这些内存块,而不是动态地分配和释放内存。内存池常用于需要频繁进行小块内存分配和释放的场景。
  • 特点和优势:
    • 提高性能: 避免了频繁的动态内存和释放操作,减少内存碎片的产生,从而提高了内存分配和释放的效率。
    • 减少内存碎片: 由于内存池预先分配了一定数量的内存块,这些内存块的大小是固定的,或者按照需求配置,因此能有效地减少内存碎片的产生。
    • 简化管理: 内存池可以有程序员精准地控制和管理,避免了内存管理带来的不确定性和性能消耗。
    • 实时性: 在需要实时性较高的系统重,内存池可以提前分配和初始化内存块,减少了运行时不可预测的延迟。
  • 工作原理: 通常由 内存块池、分配算法和回收机制 三部分组成。
    • 内存块池: 预先分配一定数量的内存块集合,每个内存块大小固定或者按需求配置。
    • 分配算法: 用于从内存块池中分配内存块的算法,通常是一种简单的分配策略。如首次适配,最佳适配。
    • 回收机制: 用于将不再使用的内存块放回到内存池中,以便下次重复使用。

5、如何避免内存泄漏?

  • 合理分配和释放内存: 确保每次分配的内存都有相应的释放操作。
  • 使用工具: 如Valgrind、AddressSanitizer等工具检测内存泄漏。
  • 代码审查: 通过代码审查发现潜在的内存泄漏问题。
  • 设计规范: 制定并遵守内存管理的设计规范和编码标准。

6、在嵌入式系统中,栈溢出的原因有哪些?如何检测和避免栈溢出?

  • 栈溢出的原因:

    • 递归调用: 过深的递归调用会导致栈空间被耗尽。
    • 过大的局部变量: 在栈上分配过大的局部变量(如大数组)会导致栈溢出。
    • 不合理的栈大小设置: 初始化时分配的栈空间不足。
  • 检测和避免栈溢出的方法:

    • 堆栈监控: 使用工具或者手动在栈顶放置哨兵值,监控栈的使用情况。
    • 合理分配栈空间: 根据系统需求合理的设置栈的空间大小。
    • 避免使用深度递归: 使用循环替代递归,避免深度递归调用。
    • 将大变量放在堆上: 堆的空间比较大,因此可以将需要大量内存的变量放在堆上,缓解栈的压力。

7、解释嵌入式系统中的内存对齐。为什么需要内存对齐?

  • 内存对齐: 是指数据在内存中的地址按照特定的边界排列。例如,4字节对齐表示数据地址必须是4的倍数。
  • 原因:
    • 硬件要求: 某些处理器要求数据按照特定的边界对齐,否则导致异常或性能下降。
    • 性能优化: 对齐数据可以提高内存的访问效率,减少CPU访问内存的次数。
    • 异常报错: 对某些严格要求的系统架构,如果不按要求对齐,会发生异常报错乃至系统崩溃。

8、如何优化嵌入式系统中的内存使用?

  • 使用内存池: 减少动态内存分配带来的碎片和开销。
  • 代码优化: 减少不必要的全局变量和静态变量,优化局部变量的使用。
  • 数据结构优化: 选择合适的数据结构,避免浪费内存。
  • 合理分配栈和堆的空间: 根据实际需求合理分配栈和堆的大小。
  • 定期检查和清理: 使用工具定期检查内存的使用情况,及时发现和清理内存泄漏。

9、malloc和free函数的工作原理?

  • malloc: 在堆上分配指定大小的内存块,返回指向该内存块的指针。如果返回失败,返回NULL
  • free: 释放malloc分配的内存块,将其归还给内存池供以后使用。
  • 工作原理:
    • malloc: 从堆上找到一个足够大的空闲内存块,标记为已使用,并返回该内存块的指针,如果没有合适的内存块,会尝试向操作系统请求更多的内存。
    • free: 将指定的内存块标记为可用,并尝试合并相邻的空闲块以减少碎片。
  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值