Ubuntu、stm32下的C程序中堆、栈、全局、局部等变量的分配地址

本文探讨了C语言程序中全局变量、局部变量、堆和栈的概念,以及它们在Ubuntu(x86)系统和STM32平台上的内存分配。实验表明,Ubuntu中栈和堆地址均向上增长,而STM32中栈地址向下减小,堆地址向上增长。通过对比分析,加深了对C程序内存分配的理解。

一、C语言程序里全局变量、局部变量、堆、栈等概念

存储区域:

内存的分配:

从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

变量的内存分配

栈区(stack):指那些由编译器在需要的时候分配,不需要时自动清除的变量所在的储存区,如函数执行时,函数的形参以及函数内的局部变量分配在栈区,函数运行结束后,形参和局部变量去栈(自动释放)。栈内存分配运算内置与处理器的指令集中,效率高但是分配的内存空间有限。

堆区(heap):指哪些由程序员手动分配释放的储存区,如果程序员不释放这块内存,内存将一直被占用,直到程序运行结束由系统自动收回,c语言中使用malloc,free申请和释放空间。

静态储存区(static):全局变量和静态变量的储存是放在一块的,其中初始化的全局变量和静态变量在一个区域,这块空间当程序运行结束后由系统释放。

常量储存区(const):常量字符串就是储存在这里的,如“ABC”字符串就储存在常量区,储存在常量区的只读不可写。const修饰的全局变量也储存在常量区,const修饰的局部变量依然在栈上。

程序代码区:存放源程序的二进制代码。

正常的程序在内存中通常分为程序段、数据段、堆栈三部分。
程序段里放着程序的机器码、只读数据,这个段通常是只读,对它的写操作是非法的。
数据段放的是程序中的静态数据。
堆栈是内存中的一个连续的块。一个叫堆栈指针的寄存器(SP)指向堆栈的栈顶。堆栈的底部是一个固定地址。堆栈有一个特点就是,后进先出。也就是说,后放入的数据第一个取出。它支持两个操作,PUSH和POP。PUSH是将数据放到栈的顶端,POP是将栈顶的数据取出。动态数据存放在堆栈中。

存储区图解:
在这里插入图片描述

补充:
Stack: 栈,存放Automatic Variables,按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
Heap: 堆,自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。
每个线程都会有自己的栈,但是堆空间是共用的。

RAM和ROM、Flash Memory的物理特性

RAM:
RAM又称随机存取存储器,存储的内容可通过指令随机读写访问。RAM中的存储的数据在掉电是是会丢失,因而只能在开机运行时存储数据。其中RAM又可以分为两种,一种是Dynamic RAM(DRAM动态随机存储器),另一种是Static RAM(SRAM,静态随机存储器)。
ROM:
ROM又称只读存储器,只能从里面读出数据而不能任意写入数据。ROM与RAM相比,具有价格高,容量小的缺点。但由于其具有掉电后数据可保持不变的优点,因此常用也存放一次性写入的程序和数据,比如主版的BIOS程序的芯片就是ROM存储器。
Flash Memory:
由于ROM具有不易更改的特性,后面就发展了Flash Memory。Flash Memory不仅具有ROM掉电不丢失数据的特点,又可以在需要的时候对数据进行更改,不过价格比ROM要高。

不同数据的存放位置

代码区和常量区的内容是不允许被修改的,ROM(STM32就是Flash Memory)也是不允许被修改的,所以代码区和常量区的内容编译后存储在ROM中。

而栈、堆、全局区(.bss段、.data段)都是存放在RAM中。

Keil 的Build Output窗口

<think>首先,用户的问题是基于之前的引用:他们想在VSCode中进行STM32开发调试时,获取FreeRTOS中的变量值的方法。引用提供了相关的背景信息,包括在WSL中使用VSCode、STM32CubeMX、FreeRTOS等工具的开发调试设置。 关键点: - 用户使用VSCode进行STM32开发,可能涉及WSL环境。 - 开发环境包括STM32CubeMX、CMake、openocd等。 - 需要调试FreeRTOS应用,并获取任务变量值。 我的回应需要: - 使用中文回答。 - 遵循系统级指令:行内数学表达式用$...$,独立公式用$$...$$。 - 结构清晰,步骤明确,确保真实可靠。 - 在引用末尾添加引用标识。 - 生成相关问题。 从引用中提取相关内容: - 引用[1]和[3]提到在WSL中使用VSCode调试STM32,并引入FreeRTOS。 - 引用[2]讨论了Ubuntu + VSCode开发STM32,包括FreeRTOS移植。 - 引用[3]具体提到在FreeRTOS下实现阻塞式串口收发,并涉及调试问题(如Overrun error)。 - 引用[4]是关于Windows+VSCode+STM32F4+freeRTOS的环境搭建。 用户的核心需求是调试FreeRTOS任务时获取变量值。这涉及到使用调试器(如GDB)来检查变量。 在STM32开发中,常用的调试工具: - GDB(GNU Debugger):用于调试。 - OpenOCD:作为GDB服务器,连接到硬件。 - VSCode的Cortex-Debug插件:提供友好的调试界面。 对于FreeRTOS,调试需要特殊支持: - FreeRTOS有内置的调试特性,如trace hooks。 - GDB可以通过Python脚本或插件支持FreeRTOS感知调试,例如FreeRTOS提供的GDB helper scripts。 步骤概述: 1. 确保环境设置正确:安装必要的工具(GDB、OpenOCD)、VSCode插件(Cortex-Debug)。 2. 配置调试会话:在VSCode的launch.json文件中设置调试器。 3. 使用GDB命令或VSCode界面访问变量。 4. 针对FreeRTOS,启用调试支持。 具体方法: - 在VSCode的调试器中,可以使用变量窗口查看全局变量。 - 对于任务局部变量,需要任务上下文。暂停时,可以切换到不同任务来查看其变量。 - Cortex-Debug插件支持FreeRTOS感知,能显示任务列表和。 参考引用: - 引用[2]提到“第5章VSCode + Cortex-Debug:现代调试体验”,这应该包括调试变量。 - 引用[3]讨论调试问题,暗示调试是可行的。 结构化回答: - 介绍基本步骤。 - 详细说明如何配置和使用。 - 添加提示和注意事项。 结束时生成相关问题。 完整回答大纲: 1. **概述**:简要解释如何在VSCode调试FreeRTOS获取变量值。 2. **前提条件**:确保环境已设置(参考引用)。 3. **配置调试器**: - 安装Cortex-Debug插件。 - 配置launch.json使用GDB和OpenOCD。 - 添加FreeRTOS支持脚本。 4. **调试步骤**: - 启动调试会话。 - 暂停执行。 - 在VSCode的变量窗口中查看全局变量。 - 通过任务上下文切换来查看局部变量。 5. **高级方法**:使用GDB命令直接查询变量。 6. **注意事项**:如引用[3]提到的潜在问题。 7. **相关问题生成**。 添加引用标识: - 在结尾处自然地添加引用,如基于引用[3]的调试建议。 数学表达式:用户问题中可能没有数学内容,但如果涉及,我会添加格式。例如,如果讨论内存地址,可以用$address$。 最终回答使用中文。 </think>### VSCode中进行STM32开发调试时获取FreeRTOS变量值的方法 在VSCode环境下调试STM32应用程序时,获取FreeRTOS任务中的变量值需要结合GDB调试器和VSCode的调试插件(如Cortex-Debug)。FreeRTOS是多任务系统,变量可能位于不同任务的全局内存中,因此调试时需确保调试器能感知任务上下文。以下是逐步指南(基于您提供的引用环境:WSL/VSCode/STM32CubeMX/CMake/openocd)。 #### 前提条件 确保您的开发环境已正确设置: - **工具链安装**:GCC(ARM工具链)、openocd(用于JTAG/SWD调试),以及VSCode插件(Cortex-Debug、C/C++)。 - **FreeRTOS集成**:通过STM32CubeMX生成代码时,启用FreeRTOS支持(例如,在CubeMX中选择FreeRTOS中间件,并配置任务)。 - **编译配置**:使用CMake或Makefile编译项目,确保生成带调试符号的elf文件(例如,编译时添加`-g`选项)。 - **引用基础**:参考引用中提到的环境搭建(如WSL+VSCode调试设置)[^1][^2]。 #### 步骤1: 配置VSCode调试会话 在VSCode中,调试通过`.vscode/launch.json`文件配置。需添加FreeRTOS感知支持,让GDB识别任务结构。 1. **安装Cortex-Debug插件**:在VSCode扩展中搜索并安装"Cortex-Debug"。此插件提供FreeRTOS调试集成。 2. **修改launch.json**: - 打开项目根目录下的`.vscode/launch.json`文件。 - 添加以下配置(基于openocd和GDB): ```json { "version": "0.2.0", "configurations": [ { "name": "Cortex Debug (FreeRTOS)", "cwd": "${workspaceRoot}", "executable": "./build/your_project.elf", // 替换为您的elf文件路径 "request": "launch", "type": "cortex-debug", "servertype": "openocd", "device": "STM32F4xx", // 根据您的芯片型号修改 "configFiles": ["openocd.cfg"], // openocd配置文件 "rtos": "FreeRTOS", // 启用FreeRTOS感知 "showDevDebugOutput": true, "runToEntryPoint": "main" } ] } ``` - **关键点**:`"rtos": "FreeRTOS"` 使调试器能自动加载FreeRTOS的GDB helper脚本(如`FreeRTOS.svd`),用于解析任务变量。 - **参考**:此配置基于引用[2]中提到的VSCode + Cortex-Debug调试体验[^2]。 #### 步骤2: 启动调试并获取变量值 调试会话启动后,通过VSCode的调试界面访问变量: 1. **启动调试**:在VSCode中按下`F5`启动调试。OpenOCD会连接硬件(如ST-Link),GDB会加载elf文件。 2. **暂停执行**: - 在代码中设置断点(例如,在任务函数内部)。 - 当程序暂停时,调试器自动显示当前任务上下文。 3. **查看变量**: - **全局变量**:直接在VSCode的"变量"窗口查看(位于左侧边栏)。FreeRTOS全局变量(如`pxCurrentTCB`)会显示。 - **任务局部变量**: - 在"调用"窗口中选择特定任务(例如,点击`vTaskStartScheduler`或自定义任务函数)。 - 切换到任务上下文后,"变量"窗口会显示该任务的局部变量。 - **使用表达式计算**:在"监视"窗口中添加变量名(如`uxTaskPriorityGet(xTaskHandle)`),直接监视任务优先级等动态值。 4. **GDB命令进阶**: - 打开VSCode的调试控制台("查看" > "调试控制台"),输入GDB命令: - 列出所有任务:`info threads`(每个线程对应一个FreeRTOS任务)。 - 切换到任务:`thread n`(`n`为任务ID)。 - 打印变量:`p variable_name`(例如,`p xQueue`显示队列句柄)。 - 查看变量:`bt full`显示完整帧和局部变量。 #### 步骤3: 解决常见问题 - **调试器无法识别任务**:确保在编译时启用了FreeRTOS的调试钩子: - 在`FreeRTOSConfig.h`中设置`configUSE_TRACE_FACILITY=1`和`configUSE_STATS_FORMATTING_FUNCTIONS=1`。 - 重新编译项目(CMake中添加`-DDEBUG`)。 - **变量值不更新**:FreeRTOS任务可能在中断上下文中,需确保暂停时任务处于活跃状态。避免优化问题:编译时使用`-O0`禁用优化。 - **硬件连接问题**:参考引用[3],确保openocd配置正确(如`openocd.cfg`指定接口为`stlink-v2`)。若有串口错误(如Overrun error),可能影响调试稳定性[^3]。 - **WSL特定提示**:在WSL中运行时,确保USB设备透传(如使用`usbipd-win`)。引用[1]提到STM32CubeMX生成的FreeRTOS代码可直接用于调试[^1]。 #### 注意事项 - **性能影响**:调试时启用FreeRTOS感知会增加内存开销,避免在生产环境中使用。 - **工具兼容性**:GDB helper脚本需匹配FreeRTOS版本(通常位于FreeRTOS源码的`FreeRTOS/Source/portable/GDB`目录)。下载FreeRTOS源码并配置路径(如引用[4]中的GCC环境设置)[^4]。 - **替代方法**:如果变量值不易访问,考虑添加日志输出(如通过串口打印任务变量),参考引用[3]的串口收发实现[^3]。 ### 相关问题 1. 如何在FreeRTOS调试中查看任务使用情况? 2. VSCode调试STM32时如何设置硬件断点以减少性能开销? 3. 在FreeRTOS多任务环境下,如何避免调试时的变量访问冲突? [^2][^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值