[求助] KEIL工程编译时的一个奇怪问题

wjroy11   2019-1-23 17:09 楼主
自己的一个KEIL工程,编译后运行,正常; 调整一下project窗口中加载的文件顺序,编译运行,直接进Hardfault。 按理说文件编译顺序不会影响最终生成的目标文件才对,不应该有不一样的运行结果啊。不明白问题出在哪里。 通过对比发现两种情况编译后生成的map文件是不一样的。别的都一样。 不知道大家有没有遇到过这个问题。求指教。
找到问题原因了,是字节对齐的问题。 工程里定义了两个比较大的数组,如下:__attribute__((aligned(4))) uint8_t MMU_US_Data_Memory[US_CAPACITY]; uint8_t MMU_SD_Data_Memory[UD_CAPACITY]; 对这两个数组的内容进行处理的时候用到了memcpy,调试发现经常在memcpy的地方进入Hardfault。调试看以上两个数组的首地址MMU_US_Data_Memory和MMU_SD_Data_Memory都不是4字节对齐的,所以讲两个数组定义改成: __attribute__((aligned(4))) uint8_t US_Data_Memory[US_CAPACITY]; __attribute__((aligned(4))) uint8_t SD_Data_Memory[UD_CAPACITY]; 在memcpy处打断点,两个数组的首地址4字节对齐了,继续运行,没出现Hardfault。 那么基本上就断定是字节对齐的问题导致的Hardfault。 有几个不明白的地方请教下: 1、为什么不加__attribute__((aligned(4))) ,申请的数组就不是字节对齐的呢?我申请数组大小是16K,跟我申请空间过大有关系吗? 2、数组字节对齐后,我试着做了这个测试: memcpy(US_Data_Memory+1,arrytest,100); 也就是说在字节对齐的US_Data_Memory数组地址基础上加了偏移量1,那么数据拷入的地址肯定就不是字节对齐了,这个时候代码是不报错的,为什么呢? 3、在调试状态下,看Disassembly窗口的汇编代码,memcpy函数对应的是:__aeabi_memcpy(),在网上查了下,这个意思是不用字节对齐的拷贝函数,如果要4字节对齐,对应的函数是__aeabi_memcpy4(),可是在汇编窗口并没有看到这个函数。不太理解。 4、为什么交换两个文件顺序之后,两个数组的首地址就会被4整除?编译文件顺序会影响数组申请地址吗? 以上四个问题,请大牛们帮忙解释下,谢谢。
本帖最后由 wjroy11 于 2019-1-24 18:05 编辑

回复评论 (31)

多打几个断点,调试一下。看看程序运行到哪里出错的。找找问题。
点赞  2019-1-23 17:13
顺序不一样时有时硬件未初始化就先进入某个中断当然死机了。
点赞  2019-1-23 17:13
具体例子拿出来看看呢
点赞  2019-1-23 17:16
引用: wenyangzeng 发表于 2019-1-23 17:13
顺序不一样时有时硬件未初始化就先进入某个中断当然死机了。

我的理解顺序不一样,只是编译的时候顺序不同,但是最终链接的hex或者bin文件应该没差别才对。按您说的硬件未初始化这个说法不太合适,比如写代码时,谁也不会刻意把初始化的文件放在最上面吧。
点赞  2019-1-23 17:21
引用: 常见泽1 发表于 2019-1-23 17:16
具体例子拿出来看看呢

工程太大了,也不适合发出来,所以只是描述一下问题表象,看大家有没有思路提供
点赞  2019-1-23 17:22
引用: wjroy11 发表于 2019-1-23 17:22
工程太大了,也不适合发出来,所以只是描述一下问题表象,看大家有没有思路提供

就是把工程里的 C文件调了顺序?
点赞  2019-1-23 17:25
引用: 常见泽1 发表于 2019-1-23 17:25
就是把工程里的 C文件调了顺序?

对,就是工程里两个文件调换一下顺序,编译也能通过,只是运行时,调换后的工程就Hardfault。我用的c++,调换的是两个cpp文件。
点赞  2019-1-23 17:27
另外一个论坛里找到一个类似的情况,跟我遇到的很像,不知道是不是同一个问题,我在研究一下。连接这个
  http://bbs.21ic.com/icview-1197474-1-1.html
点赞  2019-1-23 17:29
引用: wenyangzeng 发表于 2019-1-23 17:13
顺序不一样时有时硬件未初始化就先进入某个中断当然死机了。

严重同意
http://shop34182318.taobao.com/ https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
点赞  2019-1-23 17:52
引用: wjroy11 发表于 2019-1-23 17:21
我的理解顺序不一样,只是编译的时候顺序不同,但是最终链接的hex或者bin文件应该没差别才对。按您说的硬 ...

我觉得跟文件顺序无关,因为编译的时候编译器会自动把个个函数按照程序流程编译,最主要的原因可能是有个函数出了问题,而之前运行的时候,没有运行到这个函数,所以问题没有暴露,
点赞  2019-1-23 22:34
AB两个文件里面有什么全局的东西是一样的?是AB两个文件交换才出问题,还是任意两个文件交换都会出问题?
默认摸鱼,再摸鱼。2022、9、28
点赞  2019-1-24 00:10
引用: freebsder 发表于 2019-1-24 00:10
AB两个文件里面有什么全局的东西是一样的?是AB两个文件交换才出问题,还是任意两个文件交换都会出问题?

只是AB两文件交换才有问题,其他文件没影响
点赞  2019-1-24 09:11
引用: tiankai001 发表于 2019-1-23 22:34
我觉得跟文件顺序无关,因为编译的时候编译器会自动把个个函数按照程序流程编译,最主要的原因可能是有个 ...

工程用了很久也没发现有什么大的bug,所以感觉应该不会存在某个函数运行不到的情况
点赞  2019-1-24 09:12
引用: wjroy11 发表于 2019-1-24 09:11
只是AB两文件交换才有问题,其他文件没影响

可以的话可以把这两个文件发来看看。
默认摸鱼,再摸鱼。2022、9、28
点赞  2019-1-24 09:21
C++的话,可能涉及到构造函数的执行顺序吧。。构造函数的执行顺序不同,硬件初始化的就有先后了。。

比如全局的对象,初始化对象的时候,调用的构造函数顺序可能会不一样的。。

可以最先初始化一个串口,用来跟踪每个对象的构造函数调用情况,就知道顺序有没有差异了。。
坐而言不如起而行
点赞  2019-1-24 09:27
单纯说现象,不一定一下子就定位到,具体和工程,代码有关,,

提供不了,大家就只有一个思路了,你自己去看看,,

很大可能就是和构造函数执行顺序有关了,,这个需要你自己判断两个文件用到对象是不是需要保证一定的顺序,
坐而言不如起而行
点赞  2019-1-24 09:33
引用: wsmysyn 发表于 2019-1-24 09:33
单纯说现象,不一定一下子就定位到,具体和工程,代码有关,,

提供不了,大家就只有一个思路了,你自己 ...

感觉你的分析很合理
点赞  2019-1-24 09:40
有没有clean了后再编译试试
模电临时工
点赞  2019-1-24 09:45
引用: tiankai001 发表于 2019-1-24 09:40
感觉你的分析很合理

他说的这个问题我之前遇到类似的。。

刚看的时候,感觉C语言的可能行不大,觉得应该是C++。下边他确实说的是C++

我之前搞过一次,类代码不变,对象初始化的位置不一样,会有问题。
坐而言不如起而行
点赞  2019-1-24 09:51
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复