本帖最后由 hi201803 于 2018-3-19 21:44 编辑 版本: SWstm32 V2.40 `5 y* g+ i3 Q# T: C2 }/ ?7 x$ F6 r" e 现象: 使用stm32cubeMX 生成 代码, 然后再 SWstm32 中转换成 c++ 项目。 c++虚函数执行 出错。 下面的代码, 无法正确运行:( 在keil 中可正确运行 ). 代码只是示例,非实际项目中遇错代码. class class_17 h6 w$ f' v1 |4 X+ t# ~ { public: int a, b;, P. k$ d5 q) S, s% Q { virtual void send ( int , char*) =0;% a4 o7 V: a) G& q/ l c void fun( int i1 , char* cs1) { send (i1,cs1); };* h# F6 v3 |: r- C5 u5 ^+ N* O" L7 S };- i6 p' ]+ R) i2 r class class_2 : public class_1 { public: int a1, b1; virtual void send ( int , char*) { } ;( _/ q3 W" t; K, w" H } aclass; extern "C" void fun1(void); void fun1(void)* M$ V/ ^$ u$ v+ C( B& J9 v/ c {6 M% Z, |' R* y Z: X int i=1;( O, I8 _, a/ U' i char cs[8]; aclass.fun( 1, cs); // 函数fun 调用class_1::send , 应该变成调用 class_2:: send。 但调用一个莫名其妙的地址了.最后导致异常中断. } ====2018/03/14 增加: 测试以上代码 ================================== // 上面橙黄色代码是添加的,为了使编译通过. 不影响测试. // 然后再 main 函数中调用 fun1. extern void fun1(void); void main(void)+ \9 S3 h- A1 k9 C& } { fun1( ); while(1); } 测试结果: 1. 使用stm32cubeMX 生成 代码, 然后再 SWstm32 中转换成 c++ 项目,添加以上代码, 测试不通过 !!!! 。( o) b5 b& |) H7 o 2. 如果直接使用 swstm32 生成 C++ 程序, 添加以上代码, 测试通过 !!!!!! 。- - ====2018/03/15 增加: 原因 =================================== 原因: SWstm32 把 c 项目转化为 c++ 时, 没有修改启动代码,全局变量 的类实例 没有初始化,类实例指向虚表的指针不正确。 . M. `$ ^6 }) J& A7 E6 E2 Y 解决办法 1 : 在初始化代码中, 调用 main 函数之前, 执行: bl __libc_init_array 解决办法 2 : 直接拷贝 使用 swstm32 生成 C++ 项目的初始化代码, 替换原启动代码。 1 x: z- g* E+ P# a ( ]2 I4 e" |; f+ T" h ( w7 q6 a+ I5 `4 a. ^+ P/ {5 S8 _ 5 Q: k$ ? t9 w# ~ |
我又测试了代码, 在swstm32 的开发环境中测试的。
在一楼中添加了测试结果。
奇怪,. E+ t7 }8 g* @
c转换成c++项目中, 在map文件里面只看到 class_2 的虚表, 没有class_1的虚表。 运行不正常.! R/ `+ {! U$ v" p
但 直接使用SWStm32 生成的项目中, map文件里面看到 class_1, 和class_2 的虚表, 运行正常.
我对比两项目的c++ 编译,连接,及 链接文件, 居然没发现明显的不一样。 真是奇怪。
把两个链接脚本文件 diff 一下,某处细节肯定有差异。还有,可以尝试一下替换 GCC,用 Arm 打包的 GCC 7.2 换下 Ac6 的版本。
` T0 ?* y0 V% Q0 V9 B$ e. ]4 }: k
把链接脚本文件 都弄成一样的了,还是不行。 ( F! E. }- V5 W/ T3 q- z/ w& a
原因找到了:
启动代码没有调用 全局变量 类实例 的初始化函数,造成类实例指向虚表的指针不正确.