静态库返回的有效指针在应用代码中被识别为nullptr问题
解决TensorFlow Lite Micro静态库链接后数据指针在应用中变为nullptr的问题
问题现象
Linux x64环境下,基于TensorFlow Lite Micro构建的静态库链接到C++演示程序后,出现异常:
- 库内部
MicroInterpreter::input()方法中,TfLiteTensor的data.f是有效地址,可正常读写 - 应用层调用该方法获取
TfLiteTensor指针后,读取其data.f却显示为(nil),解引用触发段错误 - 补充测试确认:
TfLiteTensor本身的指针值在库和应用中完全一致,但数据指针仅在应用层失效,再次调用库方法时库内数据指针仍正常
相关代码片段
库内MicroInterpreter::input()方法
TfLiteTensor* MicroInterpreter::input(size_t index) { const size_t length = inputs_size(); if (index >= length) { MicroPrintf("Input index %d out of range (length is %d)", index, length); return nullptr; } if (input_tensors_[index]->data.data == nullptr) { printf("returning null data pointer\n"); } printf("returning data (idx = %ld) at %p\n", index, input_tensors_[index]->data.f); printf("data.f[0] == %f\n", (double)input_tensors_[index]->data.f[0]); input_tensors_[index]->data.f[0] = 5.f; printf("data.f[0] == %f\n", (double)input_tensors_[index]->data.f[0]); return input_tensors_[index]; }
应用层调用代码
TfLiteTensor* input = interpreter.input(0); printf("received pointer at %p\n", input->data.f);
输出验证
returning data (idx = 0) at 0x7ffe4c0f5a60 data.f[0] == 0.000000 data.f[0] == 5.000000 received pointer at (nil)
环境信息
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 5.15.0-76-generic #83~20.04.1-Ubuntu SMP
原因分析
核心原因是**TfLiteTensor结构体/联合体的布局在库和应用中不一致**:
TfLiteTensor中的data是一个联合体,编译时的宏定义、C++标准、结构体对齐选项等差异,会导致联合体成员的内存偏移量在库和应用中不同- 应用层读取
data.f时,实际访问的是库内结构体的其他内存位置,因此读出空指针;而库内访问的是正确的偏移量,所以能正常读写
解决办法
统一编译宏定义
确保库和应用编译时使用完全相同的TensorFlow Lite Micro相关宏(如TF_LITE_MICRO、TF_LITE_STATIC_MEMORY等),任何宏的差异都会导致结构体布局变化。统一编译选项
- 统一C标准:比如都使用
-std=c++17或-std=c++14,不能库用C14而应用用C++17 - 禁用自定义对齐选项:确保双方都未使用
-fpack-struct、-malign-double等修改结构体对齐的参数,保持系统默认对齐 - 统一优化级别:避免不同优化级别导致的编译器布局优化差异(建议调试阶段都用
-O0)
- 统一C标准:比如都使用
验证头文件一致性
应用和库必须使用同一版本、未修改的TensorFlow Lite Micro头文件,禁止库用修改后的头文件而应用用原始头文件,反之亦然。检查结构体偏移量
在库和应用中分别添加以下代码,验证结构体布局是否一致:#include <cstddef> // 打印TfLiteTensor中data成员的偏移量 printf("offsetof(TfLiteTensor, data): %zu\n", offsetof(TfLiteTensor, data)); // 打印联合体中f成员的偏移量 printf("offsetof(TfLiteTensorData, f): %zu\n", offsetof(TfLiteTensorData, f));如果两边输出的数值不同,直接证明布局不匹配,需排查编译选项和宏定义。
彻底重构
清理所有之前的构建产物(如make clean、删除build目录),在确保所有编译参数、宏、头文件一致后,重新编译静态库和演示程序。
内容的提问来源于stack exchange,提问作者gstukelj
相关产品推荐
相关产品推荐

