树莓派Pico运行MicroPython时hex函数是否存在内存泄漏问题?
问题根因
你碰到的崩溃不是hex()函数存在内存泄漏,也不是你的代码逻辑有误,属于MicroPython在RP2040(树莓派Pico主控)平台上的子线程内存管理特性:
- 树莓派Pico默认分配给MicroPython的堆内存仅约192KB,
hex()每次调用都会生成一个新的字符串对象存储转换后的十六进制结果,这些临时字符串属于堆内存对象 - MicroPython的自动垃圾回收(GC)默认仅在主线程的执行间隙触发,子线程的死循环中没有自动GC的调度时机,生成的临时字符串会持续占用堆内存,直到堆空间耗尽触发崩溃,你观察到的
0x16ea刚好是堆内存被临时字符串占满的临界点 - 去掉
hex()调用后,仅做整数累加操作,小整数对象在MicroPython中是静态分配的栈对象,不会占用堆内存,因此不会触发内存耗尽崩溃
修复方案
以下三种方案均可解决该问题:
- 子线程中定期手动触发GC,修改后代码如下:
import _thread import gc def myThread(): count = 0 while True: count += 1 print(hex(count)) # 每累计100次清理一次堆内存中的临时对象 if count % 100 == 0: gc.collect() _thread.start_new_thread(myThread, ())
- 将计数和打印逻辑拆分到不同线程:子线程仅做计数,将计数值存入全局变量,主线程定期读取计数值并做
hex()转换打印,主线程会自动触发GC,无需手动管理 - 避免每次调用
hex()生成新字符串:手动实现十六进制转换逻辑,复用固定长度的字节缓冲区存储转换结果,减少堆内存临时对象的生成
注意事项
MicroPython的_thread模块属于实验性功能,不同平台的线程调度、内存管理逻辑存在差异,子线程中尽量避免频繁生成临时堆对象,必要时手动控制GC时机避免内存溢出。
内容的提问来源于stack exchange,提问作者Tom Martin
相关产品推荐
相关产品推荐

