msg 包含一个有效负载,格式为 |tag|length|value| 标签的大小和长度为 2 个字节。值的大小在长度内描述, 数据类型可以是 uint16、uint32 或 uint8。
typedef struct
{
response_uint16_t msg[5];
}payload;
void func(response_uint16_t *msg, int type)
{
int *posPtr = NULL;
void *temp;
int valueLen = msg->length;
posPtr = &msg->tag;
posPtr += sizeof(msg->tag);
posPtr += sizeof(msg->length);
posPtr++; //ideally this should now point to value.
if(type == 1)
{
memcpy((U8*)temp, *posPtr, valueLen);
return(*temp);
}
if(type == 2)
{
memcpy((U16*)temp, *posPtr, valueLen);
return(*temp);
}
}
int main()
{
payload *P;
p = (struct payload*)malloc(sizeof(p));
int res;
/*assumne the msg is filled here and value expected to be filled here is of type U16 */
res =(U16)func(&p->msg[1], 2);
res =(U8)func(&p->msg[2], 1);
.
.
}
此代码片段中存在几个问题:
-
正如@Tibrogargan所评论的,
temp
指针在初始化之前被访问(复制到(; -
指针
posPtr
被声明为int *
,但它似乎是按字节前进的。
posPtr = &msg->tag; // <== pointing to `tag`
posPtr += sizeof(msg->tag); // <== pointing to element after `tag`, i.e. `length`? NO! Advanced for two integers width since size of (msg->tag) should be 2 as you said
posPtr += sizeof(msg->length); // <== pointing to element after `length`, i.e. `value`? NO! Same reason
假设您的平台整数为 32 位宽。你说"标签的大小和长度是 2 个字节"。所以posPtr += sizeof(msg->tag)
实际上是posPtr += 2
.posPtr += sizeof(msg->length)
的情况相同。
initial posPtr --> +----------------------------+
| tag | __two_bytes_pad__ |
posPtr+1 --> +----------------------------+
| length | __two_bytes_pad__ |
posPtr+2 --> +----------------------------+
| value |
+----------------------------+
同样,即使没有上述问题,以下行中的注释看起来也是错误的。posPtr
外观应指向value
之后的下一个元素。无论如何,在不知道您的实际数据结构的情况下,我无法确切地说出posPtr
指向何处。但这行值得仔细检查。
posPtr++; //ideally this should now point to value.
您假设结构已打包,但通常不是,如果在定义结构时未指定,请参阅结构填充和打包以获取更多详细信息。
指针
temp
声明为void *
因此不能直接取消引用。返回
func
的类型为void
,因此不能返回任何值。在尝试访问
value
时,您可能会假设字节序。
您需要使用如下所示的malloc
或calloc
为变量temp
分配内存:
int valueLen = msg->length;
size_t valueSize = type ==1 ? sizeof(U8) : sizeof(U16);
void *temp = malloc(valueLen * valueSize);
然后执行memcopy,以避免因将某些内容复制到变量temp
而导致Undefined behaviour
,这通常但不总是导致Seg错误,如@Tibrogargan