Zephyr中结构体深拷贝出现异常结果的问题求助
问题分析与解决方案:Zephyr BLE中央设备特征UUID存储异常
代码中的致命错误
你的代码存在两个直接导致UUID存储异常的内存分配错误:
k_calloc(1, sizeof(new_node)):new_node是指针类型,sizeof(new_node)返回的是指针字节长度(32位系统为4字节,64位为8字节),而非lst_chrc_node_t结构体的实际大小。这会导致分配的内存不足以容纳整个节点,后续赋值会破坏内存结构。正确写法为k_calloc(1, sizeof(lst_chrc_node_t))。new_node->uuid = k_calloc(1, sizeof(new_node->uuid)):同理,new_node->uuid是指针,sizeof得到的是指针大小,而struct bt_uuid结构体需要存储128位UUID数据,远大于指针长度。正确写法为k_calloc(1, sizeof(struct bt_uuid))。
Tentative UUID的含义
Zephyr中的**Tentative UUID(临时UUID)**是针对标准UUID的优化设计:
- 当BLE外设返回16位或32位的蓝牙SIG标准UUID时,Zephyr不会立即生成完整的128位UUID,而是使用
BT_UUID_TENTATIVE类型的结构体。该结构体仅存储短UUID的值,并标记类型为tentative,等到需要完整128位UUID时,再通过短UUID与蓝牙标准UUID基值(00000000-0000-1000-8000-00805F9B34FB)拼接生成。 - 若直接用
*new_node->uuid = *chrc->uuid拷贝tentative UUID结构体,只会复制短UUID部分和类型标记,不会自动扩展为完整128位UUID,这就导致你看到的存储前后UUID不一致——打印时尝试解析完整128位UUID,但实际内存中只有短UUID数据,出现乱码或错误值。
正确实现方式
修复内存分配错误后,使用Zephyr提供的bt_uuid_copy()函数拷贝UUID,该函数会自动处理tentative UUID的扩展逻辑:
typedef struct lst_chrc_node_s { sys_snode_t node; struct bt_uuid *uuid; uint16_t value_handle; uint8_t properties; uint8_t type; } lst_chrc_node_t; lst_chrc_node_t *list_create_node(struct bt_gatt_chrc *chrc, uint8_t type) { // 修复:分配结构体大小的内存 lst_chrc_node_t *new_node = k_calloc(1, sizeof(lst_chrc_node_t)); if (!new_node) return NULL; // 修复:分配struct bt_uuid大小的内存 new_node->uuid = k_calloc(1, sizeof(struct bt_uuid)); if (!new_node->uuid) { k_free(new_node); return NULL; } print_uuid128("UUID that will be store", chrc->uuid); // 使用bt_uuid_copy替代直接结构体赋值 bt_uuid_copy(new_node->uuid, chrc->uuid); new_node->value_handle = chrc->value_handle; new_node->properties = chrc->properties; new_node->type = type; print_uuid128("UUID that was stored ", new_node->uuid); return new_node; }
额外注意事项
- 销毁链表节点时,需先调用
k_free(new_node->uuid),再调用k_free(new_node),避免内存泄漏。 - 若仅需处理短UUID,可直接存储
uint16_t或uint32_t类型的短UUID值,节省内存,但需注意区分UUID的位数类型。
内容的提问来源于stack exchange,提问作者Groux
相关产品推荐
相关产品推荐

