当前位置: 首页 > ai >正文

freertos下printf(“hello\r\n“)和printf(“hello %d\r\n“,i)任务堆栈消耗有何区别

一 背景

原先做的项目,TCP通讯采用stm32f103+freertos+w5500方案,实现的tcp单连接通信,同事提了个需求让实现tcp多连接,于是改了一版代码。测试发现根本跑不起来,程序应该是卡死崩溃了,相关问题代码如下:

void do_tcp_server(void)
{switch(wizGetSnSR(tcp_socket[i].sock_num))                                                /*获取socket的状态*/{case SOCK_CLOSED: printf("SOCK %d CLOSED\r\n",tcp_socket[i].sock_num);                                            /*socket处于关闭状态*/socket(tcp_socket[i].sock_num ,Sn_MR_TCP,local_port,Sn_MR_ND);         /*打开socket*/break;case SOCK_INIT:   printf("SOCK %d INIT\r\n",tcp_socket[i].sock_num);                                                       /*socket已初始化状态*/listen(tcp_socket[i].sock_num);                                                   /*socket建立监听*/break;...}
}

在上面这段代码里面,如果我将打印

 printf("SOCK %d CLOSED\r\n",tcp_socket[i].sock_num);printf("SOCK %d INIT\r\n",tcp_socket[i].sock_num);

改为

 printf("SOCK CLOSED\r\n");printf("SOCK INIT\r\n");

则程序运行正常。

二 定位分析过程

  1. 大方向是堆栈溢出
    问了下chatgpt是说printf(“hello”)和printf(“%d”)格式化打印,消耗的堆栈是不一样的,前者纯字符串,压栈的时候只是个地址,而后者则要压入更多内容。这么说来应该是堆栈溢出问题。于是我将打印改为printf(“SOCK CLOSED\r\n"”)和printf(“SOCK INIT\r\n")在另一个任务里面调用vTasklist打印出任务堆栈信息如下:
Name          State  Prio  Stack  Num
greenLedTask   	R	3	86	3
yellowLedTask  	R	3	86	4
beepLedTask    	R	3	86	6
tcpServerTask  	R	3	0	1
redLedTask     	X	3	0	5
mail_station   	R	3	88	2
IDLE           	R	0	107	7

关联的任务函数tcpServerTask剩余堆栈大小是0,也就是说此时该任务已经没有堆栈空间了,printf改为%d打印,多一点就可能导致堆栈溢出;

2.堆栈消耗能差多少呢
我将tcpServerTask任务堆栈大小由128word改为256word,然后打印两种情况下的剩余对战情况:

//printf(“SOCK CLOSED\r\n"”)和printf(“SOCK INIT\r\n")
Name          State  Prio  Stack  Num
greenLedTask   	R	3	86	3
yellowLedTask  	R	3	86	4
beepLedTask    	R	3	86	6
tcpServerTask  	R	3	106	1
redLedTask     	X	3	0	5
mail_station   	R	3	88	2
IDLE           	R	0	107	7
//printf("SOCK %d CLOSED\r\n",tcp_socket[i].sock_num);
//printf("SOCK %d INIT\r\n",tcp_socket[i].sock_num);Name          State  Prio  Stack  Num
redLedTask     	X	3	0	5
tcpServerTask  	R	3	57	1
IDLE           	R	0	109	7
greenLedTask   	B	3	86	3
yellowLedTask  	B	3	86	4
beepLedTask    	B	3	86	6
mail_station   	B	3	88	2

根据打印结果看printf%d格式化输出比单纯打印纯字符串,任务堆栈要多消耗50个word大小左右,所以在你任务本身剩余堆栈很少的情况下,一个printf打印就可能导致溢出,程序崩溃。

  1. 最后解决方案

由于多链接,这里打印最好能打印出socket编号,所以

  1. 增加总的堆内存大小5000-》8192
  2. 增加printf%d打印任务堆栈大小128-》256
configTOTAL_HEAP_SIZE                    ((size_t)8192)
osThreadDef(tcpServerTask, StartTcpServerTask, osPriorityNormal, 0, 256);
http://www.xdnf.cn/news/19964.html

相关文章:

  • 金贝 KA Box 1.18T:一款高效能矿机的深度解析
  • Python 第三方自定义库开发与使用教程
  • Redis是单线程的,为啥那么快呢?经典问题
  • 第六章 Cesium 实现简易河流效果
  • 热计量表通过M-Bus接口实现无线集抄系统的几种解决方
  • 2025国赛C题题目及最新思路公布!
  • ubuntu20.04配置运行ODM2.9.2教程,三维重建,OpenDroneMap/ODM2.9.2
  • 智能家居芯片:技术核心与创新突破
  • Spring Cloud Ribbon 核心原理
  • 数字化转型:从锦上添花到生存必需——2025年零售行业生存之道
  • Function Call实战:用GPT-4调用天气API,实现实时信息查询
  • Matlab中的积分——函数int()和quadl()
  • PDF24 Creator:免费的多功能PDF工具
  • OPC UA双层安全认证模型解析
  • 【蓝桥杯选拔赛真题64】C++最大空白区 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解
  • 大小端存储的理解与判断方法
  • Cypress 测试框架:轻松实现端到端自动化测试!
  • 从零开始的python学习——元组
  • PostgreSQL与SQL Server:B树索引差异及去重的优势
  • Webus 与中国国际航空合作实现 XRP 支付
  • DeepSeek文献太多太杂?一招制胜:学术论文检索的“核心公式”与提问艺术
  • Java+Vue构建的MES智能管理系统,集成生产计划、执行、监控与优化功能,支持产品、车间、工艺、客户、供应商等多维度管理,含完整源码,助力企业高效生产
  • LeetCode算法日记 - Day 31: 判定是否互为字符重排、存在重复元素
  • nextcyber——常见应用攻击
  • Dubbo分布式服务框架全解析
  • 轻松上手 qData 数据中台开源版:Docker Compose 助你10分钟跑起来
  • matlab薄透镜对物体成像
  • 数据库小册(1)
  • Day35 网络协议与数据封装
  • 开讲了,全栈经验之谈系列:写给进阶中的小伙伴