ESP8266异常在尝试从字节数组读取float时
ESP8266 Exception while trying to read float from byte array
我在这里有一个奇怪的问题(WEMOS D1 mini)。我正在旋转一个用于使用NRF24L01发射器的网络的库。
我定义了一个Gloabl Uint8_t Arry,它代表我的接收缓冲区。从另一个设备接收传输时,阵列会填充。填充数组后,我开始解析缓冲区,以确定是否有有效的标头/帧。标头包含一些典型数据,例如发件人,校验和...如果标题有效,则帧的数据将被解析。数据的结构始终相同。可以有x所谓的datatriples。DataTriph是密钥(CSTRING),值类型(UINT8_T)和值本身的组合。值类型可以是基本类型,例如int8,uint8或float或string。
现在是Stange Thing。
为了保存内存,我不将值从缓冲区复制到专用变量中。我一直指向缓冲区中的位置。当我想阅读一个值时,我会做一个简单的指针并读取值。如果值是字符串或简单的1个字节长UINT8_T,则这是非常有效的。但是,如果是浮点或uint32_t,我会得到一个告诉我的loadStorSorealignmentcause excetion,我想访问不访问的内存。怎么会这样?指针绝对指出了正确的缓冲液。我对此进行了检查,因为如果我创建一个新的浮点变量,并从缓冲区到变量地址做一个memcpy,那么一切都很好。但是我A创建了一个浮点指针,并指向缓冲区中的位置,我得到了一个例外。
有人可以告诉我原因或告诉我我做错了什么?
这是一些代码片段,可以更好地理解。
bool SBSmartHomeBasicDevice::parseDataTriples() {
if (_IncommingTransmission) {
uint8_t* iCurrentPos;
uint8_t iDataTripleCount = 0;
// _LastReceivedFrame.Payload points to the receive buffer
for (iCurrentPos = _LastReceivedFrame.Payload; iCurrentPos < (_LastReceivedFrame.Payload + _LastReceivedFrame.Header.PayloadSize); iCurrentPos) {
// Catch the type of the triple
uint8_t type = *((uint8_t*)iCurrentPos);
// increase the pointer about uint8_t size
iCurrentPos += sizeof(uint8_t);
// Catch the key of the triple
char* key;
key = (char*)(iCurrentPos);
// increase the pointer about strlen of key + 1
iCurrentPos += strlen((char*)iCurrentPos) + 1;
// catch the value
void* value = (void*)(iCurrentPos);
_LastReceivedTriples[iDataTripleCount].setType(type);
_LastReceivedTriples[iDataTripleCount].setKey(key);
// ***
// Here starts the interesting part
// ***
float* fTmp = (float*)iCurrentPos;
// The following works perfect
// ****
float f;
memcpy(&f, fTmp, sizeof(float));
Serial.println(f);
// ****
// The following causes an exception
Serial.println(*fTmp);
// *** EXCEPTION ***
_LastReceivedTriples[iDataTripleCount].setValue(iCurrentPos);
// now increase the pointer
switch (type) {
case SMART_HOME_VALUE_TYPE_STRING:
iCurrentPos += strlen((char*)iCurrentPos) + 1;
break;
case SMART_HOME_VALUE_TYPE_INT8:
case SMART_HOME_VALUE_TYPE_UINT8:
iCurrentPos += sizeof(int8_t);
break;
case SMART_HOME_VALUE_TYPE_INT16:
case SMART_HOME_VALUE_TYPE_UINT16:
iCurrentPos += sizeof(int16_t);
break;
case SMART_HOME_VALUE_TYPE_FLOAT:
iCurrentPos += sizeof(float);
break;
case SMART_HOME_VALUE_TYPE_INT32:
case SMART_HOME_VALUE_TYPE_UINT32:
iCurrentPos += sizeof(int32_t);
break;
default:
Serial.println("parseDataTriples(): Unknown ValueType");
}
_LastReceivedTriples[iDataTripleCount].print();
iDataTripleCount++;
_LastReceivedTriplesCount = iDataTripleCount;
}
return true;
}
return false;
}
非常感谢您抽出宝贵的时间并帮助我。
问候Schullebernd
ESP8266只能读取float
S(和16位int
S,32位int
s,double
s)从正确对齐的地址,即地址,即是数据类型的多个地址。由于 float
是4个字节长,因此只能从4个倍数的地址读取4个字节。否则您会得到上述例外。
您正在使用uint8_t
数组。uint8_t
是1个字节长,因此不需要,并且可能不会以任何方式对齐。数组可能从地址170001开始。如果您现在在数组中的位置40处具有float
值,则您的代码试图从地址170041读取float
值,该值未正确对齐并导致例外。
解决方案是首先将float
值的字节复制到局部,正确对齐的变量。那就是您要做的,但随后您在不对准的位置再次访问并获得例外。
float* fTmp = (float*)iCurrentPos; // does not copy; takes a pointer to the orignal location
float f;
memcpy(&f, fTmp, sizeof(float)); // copies data to aligned variable
Serial.println(f); // prints value from aligned variable
Serial.println(*fTmp); // prints value for original, non-aligned location
只是摆脱了最后一行。
- 输出没有重复元素的动态数组(收缩数组)C++
- 将字符串转换为无符号字符数组/字节数组
- 检查彩虹数组(检查数组的反向样式是否与自身匹配)
- 如何创建对齐的数组 c++ 数组?
- 查找数组中数组元素的重复出现?
- C++释放带有子数组的数组的内存分配
- 返回一个数组,该数组包含数组中的数量,该数组数量较小或等于给定数组中的元素
- 通过键盘输入字符串数组和 int 数组的数组大小
- 如何在C 中创建类似于Python的Numpy数组的数组
- 无法获取数组内数组的总和
- C4838 警告,包含常量字符* 数组的数组初始化
- 连接数组,数组 1 内存消失C++
- 如何在C++中创建二维数组的数组
- 获取字符数组C++数
- 2D数组中数组下标的类型"int[int]"无效
- C 模板类动态数组的数组到数组
- 结构数组的数组
- 如何制作具有动态大小的数组?动态数组的一般用法(可能还有指针)
- 对象的数组-STD ::数组 - 构造函数初始化问题
- 使用SSE内部函数将布尔数组(8字节布尔)转换为int或char