使用DART FFI调用C++函数返回结果每次执行不一致的原因
动态库返回指针导致结果不一致的问题分析与修复
编译通过但重复运行返回结果不一致:当length=20时连续10次结果一致,length=5时每次运行结果不同。
问题代码
C++ 代码
#include <vector> #include <iostream> extern "C" int* get_int_array(int size); int* get_int_array(int size) { std::vector<int> vec(size); for (int i = 0; i < size; i++) { vec[i] = i; } int* arr = vec.data(); std::cout << "C++ Result" << std::endl; for (int i =0; i< size; i++) { std::cout << arr[i] << ","; } std::cout << std::endl; return arr; } // 编译命令:g++ -shared -lstdc++ -o user_func.dll user_func.cpp -Wl,--output-def,user_func.def,--out-implib,libuser_func.a
Dart 代码
import 'dart:ffi'; void main() { final path = './user_func.dll'; final _lib = DynamicLibrary.open(path); // int* get_int_array(int size) final getIntPtr = _lib.lookupFunction<Pointer<Int32> Function(Int32), Pointer<Int32> Function(int)>('get_int_array'); final length = 5; final ptr = getIntPtr(length); final array = ptr.asTypedList(length); print('\nDart Result'); print(ptr); print(array); }
问题根源
核心问题是悬空指针:C++函数中的std::vector<int> vec是局部变量,函数执行完毕返回时,vec会被销毁,其内部管理的堆内存会被释放。此时返回的vec.data()指针变成悬空指针,指向的内存已不属于程序有效内存。
后续Dart访问这块内存时,内存可能已被其他操作覆盖(比如栈帧复用、堆内存重新分配),导致结果随机。length=20时看似稳定,只是这块内存暂时未被覆盖,属于未定义行为的偶然表现,本质仍然错误。
修复方案
方案1:C++动态分配内存,Dart主动释放
在C++中用new[]动态分配数组,返回指针,同时提供释放函数让Dart调用,避免内存泄漏。
修改后的C++代码:
#include <iostream> extern "C" int* get_int_array(int size); extern "C" void free_int_array(int* arr); int* get_int_array(int size) { int* arr = new int[size]; for (int i = 0; i < size; i++) { arr[i] = i; } std::cout << "C++ Result" << std::endl; for (int i =0; i< size; i++) { std::cout << arr[i] << ","; } std::cout << std::endl; return arr; } void free_int_array(int* arr) { delete[] arr; }
修改后的Dart代码:
import 'dart:ffi'; void main() { final path = './user_func.dll'; final _lib = DynamicLibrary.open(path); // int* get_int_array(int size) final getIntPtr = _lib.lookupFunction<Pointer<Int32> Function(Int32), Pointer<Int32> Function(int)>('get_int_array'); // void free_int_array(int* arr) final freeIntArray = _lib.lookupFunction<Void Function(Pointer<Int32>), void Function(Pointer<Int32>)>('free_int_array'); final length = 5; final ptr = getIntPtr(length); final array = ptr.asTypedList(length); print('\nDart Result'); print(ptr); print(array); // 释放动态分配的内存,避免泄漏 freeIntArray(ptr); }
方案2:Dart分配内存,C++填充数据
由Dart负责内存分配,将内存指针传递给C函数,C直接填充数据。这种方式无需手动释放内存,内存由Dart的GC管理。
修改后的C++代码:
#include <iostream> extern "C" void fill_int_array(int* arr, int size); void fill_int_array(int* arr, int size) { for (int i = 0; i < size; i++) { arr[i] = i; } std::cout << "C++ Result" << std::endl; for (int i =0; i< size; i++) { std::cout << arr[i] << ","; } std::cout << std::endl; }
修改后的Dart代码:
import 'dart:ffi'; import 'dart:typed_data'; void main() { final path = './user_func.dll'; final _lib = DynamicLibrary.open(path); // void fill_int_array(int* arr, int size) final fillIntArray = _lib.lookupFunction<Void Function(Pointer<Int32>, Int32), void Function(Pointer<Int32>, int)>('fill_int_array'); final length = 5; final array = Int32List(length); fillIntArray(array.dataAsPointer(), length); print('\nDart Result'); print(array); }
内容的提问来源于stack exchange,提问作者user18756621
相关产品推荐
相关产品推荐

