Arduino Nano执行memcpy时崩溃,求原因分析
Arduino Nano执行memcpy时崩溃的原因分析
问题场景
在Arduino Nano开发中,我们通过decrypt函数解密Base64编码的rxPacket得到字符串decryptedRes,尝试提取最后一个^前的内容时,执行memcpy引发设备崩溃:
基础定义代码
const uint8_t RX_MSG_MAX_LENGTH = 160; char rxPacket[RX_MSG_MAX_LENGTH]; const char *decrypt(const char *base64Text) { // ... 解密逻辑实现 return (char*) message; } const char *decryptedRes = decrypt(rxPacket);
提取逻辑代码
// verify checksum //char checker[RX_MSG_MAX_LENGTH] = ""; char * checker = new char[strlen(decryptedRes) + 1]; const char * pos = strrchr(decryptedRes, '^'); if (pos != nullptr) { uint8_t length = pos - decryptedRes + 1; // 包含分隔符^的长度 memcpy(checker, decryptedRes, length); // 执行此处时Nano崩溃 checker[length] = '\0'; // ... 后续校验逻辑 }
崩溃原因分析
1. 动态内存分配失败(最可能原因)
Arduino Nano搭载的ATmega328P芯片仅拥有2KB SRAM,扣除系统占用后可用内存极为有限:
- 当剩余内存不足以分配
strlen(decryptedRes)+1字节的连续空间时,new会返回空指针(AVR平台下直接触发内存访问错误)。 - 后续
memcpy操作空指针指向的非法内存,直接导致设备崩溃。 - 此外,AVR平台的动态内存管理易产生内存碎片,即使总剩余内存足够,也可能因碎片无法分配连续空间导致分配失败。
2. decrypt函数返回非法内存
如果decrypt函数内部的message是栈内存(例如char message[RX_MSG_MAX_LENGTH];),函数返回后栈内存会被系统回收复用:
- 虽然
Serial.println(decryptedRes)可能暂时打印出正确内容(栈内存尚未被覆盖),但后续执行strlen、strrchr、memcpy时,栈内存已被其他操作覆盖,访问非法内存引发崩溃。
3. 长度计算溢出风险
length被定义为uint8_t(8位无符号整数,最大值255):
- 若
decryptedRes的长度超过255,pos - decryptedRes + 1的结果会溢出,变成远小于实际值的错误数值。 - 虽不会直接导致
memcpy崩溃,但后续使用checker时会因数据截断引发逻辑错误,间接导致设备异常。
内容的提问来源于stack exchange,提问作者Musa P.
相关产品推荐
相关产品推荐

