You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台TFLite C++调用Invoke()触发段错误问题求助

问题

开发基于TFLite的Android C++应用,自行编译.so库失败后使用网上预编译库,测试项目中运行正常,但集成到实际项目后调用this->m_interpreter->Invoke()时触发段错误。项目采用双线程架构:一个线程获取输入,另一个线程调用TFLite;构造函数仅执行一次,run函数每帧调用,已确认输入参数、尺寸及初始化均正常。

相关代码

tflite.cpp

#include "tflite.hpp"

    tflite::tflite(uint8_t *data, size_t size)
    {
        try
        {
            lib_tflite::ErrorReporter* error_reporter;

            this->m_env = lib_tflite::FlatBufferModel::BuildFromBuffer((const char *)data, size, error_reporter);

            lib_tflite::ops::builtin::BuiltinOpResolver resolver;

            lib_tflite::InterpreterBuilder(*this->m_env, resolver)(&m_interpreter);

            if (m_interpreter->AllocateTensors() != kTfLiteOk)
            {
                throw std::runtime_error("Failed to allocate tensor");
            }
            m_interpreter->SetNumThreads(2);

            this->m_input_node_count = m_interpreter->inputs().size();
            this->m_output_node_count = m_interpreter->outputs().size();

            for (size_t idx = 0; idx < this->m_input_node_count; ++idx)
            {
                int input = m_interpreter->inputs()[idx];
                auto height =   m_interpreter->tensor(input)->dims->data[1];
                auto width =    m_interpreter->tensor(input)->dims->data[2];
                auto channels = m_interpreter->tensor(input)->dims->data[3];

                std::vector<int> res = {(int)this->m_input_node_count, channels, width, height};
                this->m_inputDims.push_back(res);

                const TfLiteTensor* input_tensor = m_interpreter->input_tensor(idx);

                size_t element_count = 1;
                for (int i = 0; i < input_tensor->dims->size; i++)
                {
                    element_count *= input_tensor->dims->data[i];
                }

                this->m_input_elem_size.push_back(element_count);
            }

            for (size_t idx = 0; idx < this->m_output_node_count; ++idx)
            {
                int output = m_interpreter->outputs()[idx];
                auto height =   m_interpreter->tensor(output)->dims->data[1];
                auto width =    m_interpreter->tensor(output)->dims->data[2];
                auto channels = m_interpreter->tensor(output)->dims->data[3];

                std::vector<int> res = {(int)this->m_output_node_count, channels, width, height};
                this->m_outputDims.push_back(res);

                const TfLiteTensor* output_tensor = m_interpreter->output_tensor(idx);

                int element_count = 1;
                for (int i = 0; i < output_tensor->dims->size; i++) {
                    element_count *= output_tensor->dims->data[i];
                }
                this->m_output_elem_size.push_back(element_count);
            }

            for (size_t idx = 0; idx < this->m_input_node_count; ++idx)
            {
                this->m_input_buffer.emplace_back(this->m_input_elem_size[idx], 0
                );
            }

            for (size_t idx = 0; idx < this->m_output_node_count; ++idx)
            {
                this->m_output_buffer.emplace_back(this->m_output_elem_size[idx], 0
                );
            }
    }

    bool tflite::run(std::vector<float> &t_out_buffer,
                     std::vector<float> &t_cls_buffer,
                     std::vector<float> &t_buffer,
                     size_t region_size) noexcept
    {

        for(size_t idx = 0; idx < this->m_input_node_count; idx++)
        {
            float* data_ptr = m_interpreter->typed_input_tensor<float>(idx);
            memcpy(data_ptr, t_buffer.data(), this->m_input_elem_size[idx]);
        }

        // This is where it fails
        if (kTfLiteOk != this->m_interpreter->Invoke())
        {
            log_error("Failed to invoke\n");
            return false;
        }

        for(size_t idx = 0; idx < this->m_output_node_count; idx++)
        {
            float* output = this->m_interpreter->typed_output_tensor<float>(idx);

            this->m_output_buffer[idx] = std::vector<float> (output,
                                                             output + this->m_output_elem_size[idx]);
        }

        t_cls_buffer = this->m_output_buffer[0];
        t_out_buffer =  m_output_buffer[1];
    }

/* end_of_file */

tflite.hpp

#ifndef TFLITE_DRIVER_HPP
#define TFLITE_DRIVER_HPP

#include <memory>

#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/optional_debug_tools.h"

    namespace lib_tflite = ::tflite;

    class tflite
    {
    public:

        tflite() = delete;

        virtual ~tflite() noexcept = default;

        tflite(tflite &&) = delete;

        tflite & operator=(tflite &&) = delete;

        tflite(const tflite &) = delete;

        tflite & operator=(const tflite &) = delete;

        tflite(uint8_t *data, size_t size);

        bool run(   std::vector<float> &t_out_buffer,
                    std::vector<float> &t_cls_buffer,
                    std::vector<float> &t_buffer,
                    size_t region_size) noexcept;
    private:
        lib_tflite::ErrorReporter* error_reporter;
        
        lib_tflite::ops::builtin::BuiltinOpResolver resolver;

        std::unique_ptr<lib_tflite::FlatBufferModel> m_env;

        std::unique_ptr<lib_tflite::Interpreter> m_interpreter;

        std::vector<const char *> m_input_names;

        std::vector<const char *> m_output_names;

        size_t m_input_node_count;

        size_t m_output_node_count;

        std::vector<lib_tflite::Tensor> m_inputTensors;

        std::vector<lib_tflite::Tensor> m_outputTensors;

        std::vector<size_t> m_input_elem_size;

        std::vector<size_t> m_output_elem_size;

        std::vector<std::vector<int>> m_inputDims;

        std::vector<std::vector<int>> m_outputDims;

        std::vector<std::vector<float>> m_input_buffer;

        std::vector<std::vector<float>> m_output_buffer;

        std::unique_ptr<lib_tflite::MemoryAllocation> m_memory_info;

    };

#endif // TFLITE_DRIVER_HPP
/* end_of_file */

错误日志

E/libc: Access denied finding property "ro.mediatek.platform"
E/libc: Access denied finding property "ro.chipname"
A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x13c6759bfc61 in tid 27936 (processing), pid 27893 (ample.nerveblox)
排查分析与解决建议

1. 线程安全问题

TFLite的Interpreter并非线程安全对象,即使构造函数在单线程执行,若run函数在另一个线程调用且无同步机制,会导致Interpreter内部状态被破坏,触发段错误。

  • 解决方法:在类的private成员中添加std::mutex m_interpreter_mutex,然后在run函数关键代码段添加锁:
    bool tflite::run(...) noexcept
    {
        std::lock_guard<std::mutex> lock(m_interpreter_mutex);
        // 原有输入拷贝、Invoke、输出拷贝代码
    }
    

2. 预编译库与项目环境不匹配

测试项目和实际项目的ABI架构、NDK版本、编译参数可能存在差异,预编译库在测试环境兼容,但实际项目中因不匹配导致内存访问错误。

  • 解决方法:
    • 确认实际项目的ABI设置(如arm64-v8a/armeabi-v7a)与预编译库一致;
    • 检查项目NDK版本是否与预编译库编译时的NDK版本匹配;
    • 尝试用实际项目的编译环境重新编译TFLite库。

3. 输入数据拷贝越界

run函数中memcpy的第三个参数是元素数量,但memcpy按字节拷贝,未乘以sizeof(float)会导致拷贝长度不足;同时未校验t_buffer的实际大小,若小于m_input_elem_size[idx]会触发越界,破坏Interpreter内部结构。

  • 解决方法:添加大小校验并修正拷贝长度:
    for(size_t idx = 0; idx < this->m_input_node_count; idx++)
    {
        if (t_buffer.size() != this->m_input_elem_size[idx]) {
            log_error("Input buffer size mismatch\n");
            return false;
        }
        float* data_ptr = m_interpreter->typed_input_tensor<float>(idx);
        memcpy(data_ptr, t_buffer.data(), this->m_input_elem_size[idx] * sizeof(float));
    }
    

4. ErrorReporter未正确初始化

构造函数中error_reporter未初始化就传入BuildFromBuffer,可能导致TFLite内部错误报告时访问空指针,间接引发段错误。

  • 解决方法:使用默认ErrorReporter:
    auto error_reporter = lib_tflite::DefaultErrorReporter();
    this->m_env = lib_tflite::FlatBufferModel::BuildFromBuffer((const char *)data, size, error_reporter);
    

5. Interpreter有效性检查

确认tflite对象未被意外销毁、m_interpreter指针未被非法修改,可在run函数开头添加检查:

if (!m_interpreter) {
    log_error("Interpreter is null\n");
    return false;
}

内容的提问来源于stack exchange,提问作者Turgut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:21:48