为何代码g++编译运行正常,在Micropython环境运行报std::out_of_range错误
问题根因
你遇到的报错本质是csv_data为空向量时调用at(0)触发了越界异常,单独用g++编译正常、作为Micropython模块运行报错的核心原因是运行时的工作目录不一致:
- 单独运行自行编译的
myapp时,你是在A00068.csv文件所在的目录执行程序,用相对路径可以正常找到文件 - 作为Micropython模块运行时,你是在
micropython/ports/unix/目录启动的Micropython进程,代码用相对路径"A00068.csv"会尝试在ports/unix/目录下找文件,找不到的情况下ifstream直接打开失败,read_csv返回空的二维向量,后续调用csv_data.at(0)就会抛出越界异常。
另外还有一个隐性问题:Micropython核心是纯C实现的,你通过extern "C"导出的函数如果抛出C++异常,C层无法处理会直接触发进程abort,这也是你没有收到更友好错误提示的原因。
解决方案
1. 修复文件路径问题
二选一即可:
- 把
A00068.csv文件复制到你启动Micropython的目录,也就是micropython/ports/unix/路径下 - 直接使用绝对路径读取文件,比如
read_csv("/home/pi/projects/xxx/A00068.csv"),路径替换为你实际的文件存放路径 - (更灵活的方案)修改
cppfunc支持从Micropython层传入文件路径参数,避免写死路径。
2. 增加边界判断与错误日志
补充文件读取失败、文件为空的判断逻辑,避免非法访问:
首先在read_csv函数开头增加文件打开判断:
vector<vector<double> > read_csv(const char *filename) { ifstream read_file(filename); // 新增:判断文件是否成功打开 if (!read_file.is_open()) { mp_printf(&mp_plat_print, "文件打开失败:%s\n", filename); return {}; } // 原有逻辑不变 }
然后在调用read_csv之后先判断向量是否为空:
vector<vector<double> > csv_data = read_csv("A00068.csv"); // 新增边界判断 if (csv_data.empty() || csv_data[0].empty()) { mp_printf(&mp_plat_print, "CSV文件为空或读取失败\n"); delete[] ecg_series; // 释放已经申请的内存避免泄漏 return mp_const_none; } int len = csv_data.at(0).size();
3. 捕获C++异常避免直接崩溃
因为C代码无法处理C异常,需要把所有C逻辑包在try-catch块内:
mp_obj_t cppfunc() { try { // 原有所有逻辑都放在try块内 clock_t startTime,endTime; startTime = clock(); // ... 剩余原有代码 ... return mp_const_none; } catch (const std::exception& e) { mp_printf(&mp_plat_print, "运行错误:%s\n", e.what()); return mp_const_none; } }
4. 修复内存泄漏问题
你当前代码里用new申请的ecg_series数组没有释放,运行多次会出现内存泄漏,建议要么用完加delete[] ecg_series;释放,要么直接用vector<double> ecg_series(15095976);自动管理内存。
内容的提问来源于stack exchange,提问作者Vaibhav Vishwakarma
相关产品推荐
相关产品推荐

