硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1710|回复: 10
收起左侧

[MDK] keil的两个恶心bug

  [复制链接]

17

主题

82

回帖

133

积分

初级会员

积分
133
发表于 2024-5-29 17:04:09 | 显示全部楼层 |阅读模式
本帖最后由 fantasyhpu 于 2024-5-30 14:16 编辑

很多人使用keil时遇见过这个恶心bug: Encountered an improper argument

其实它还有另外一个恶心bug: keil c51的局部变量名能影响编译结果。这个恶心bug是我最近遇见的,不知道坛友遇见过没有。
复现代码非常简单,普通的C51代码:
[C] 纯文本查看 复制代码
#include "reg52.h"
#include "stdio.h"
#include "intrins.h"

void uart_init()
{
        SCON = 0x52;
        TMOD = 0x20;
        TH1  = 0xfd;
        TL1  = 0xfd;
         TR1  = 1;
}

void main()
{        
        unsigned int a=17; // 注意局部变量a的名字造成了该bug
        unsigned int b;
        uart_init();
        for(b=2;b<=a-1;b++)
        {
                if(a%b==0)
                        break;
        }
        if(b<a)
                printf("%d is not a prime number",a);
        else
                printf("%d is a prime number",a);
        while(1);
}


具体过程是:
1. 解压附件test2.zip,然后使用main.c中的代码,新建一个C51工程,注意main()函数中第一行的局部变量名字“a”,正是这个名字造成了该bug。
2. 编译新建的C51工程,然后可以软件仿真一下,一切正常,这表明第一次编译后生成的.hex文件正常。(也可以不软件仿真,直接将.hex文件下载到单片机中,第一次编译的.hex文件正常运行)
3. 退出仿真界面,重复编译一下后,生成的.hex文件就不正常了,可以软件仿真看看,观察局部变量a和b的值,单步运行表明它俩在乱跳。这表明第二次编译该工程后,生成的.hex文件就不正常了。(也可以不软件仿真,直接将.hex文件下载到单片机中,后续编译的.hex文件不能正常运行)
4. 若将main()函数中的局部变量a和b挪到函数外面成为全局变量,则无论编译多少次,生成的.hex文件都是正常的。

不想新建工程的坛友可以观察下面的gif动画,注意在第二次编译后,局部变量a和b的值就不正常了。(用的是从官网下的最新的keil c51v961版本)



111.gif

test2.zip

29.99 KB, 下载次数: 2

回复

使用道具 举报

10

主题

99

回帖

129

积分

初级会员

积分
129
发表于 2024-5-29 20:07:26 | 显示全部楼层
用Watch看局部变量,会存在问题。这个不一定是keil的问题。你可以把a变成staic变量,就可以了。。。原理我理解的,keil解析编译文件的时候,因为局部变量a可能存在多个函数里面,是无法解析正确地址的。但是,静态变量的地址是唯一确定的。
回复

使用道具 举报

20

主题

121

回帖

181

积分

初级会员

积分
181
发表于 2024-5-29 20:11:35 | 显示全部楼层

局部变量在重新编译后,是需要重新添加的,否会异常!

使用C51 V9.0版本编译首次后查看变量a正常0x11
退出重新编译文件后查看a和b变量,初始化赋值后如下图
1.png
确实不正常,但是上次存在的a和b变量前会多了一个符号点,
重新添加变量a和b,如下图,变量是正常的
2.png





回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2024-5-29 21:11:12 | 显示全部楼层
Encountered an improper argument
这个真的恶心人,关都关不掉,无奈写了AHK脚本,检测到这个弹窗,就把keil进程杀掉强制重启
回复

使用道具 举报

10

主题

99

回帖

129

积分

初级会员

积分
129
发表于 2024-5-30 00:14:51 | 显示全部楼层
补充说明一下,纯个人理解,并不一定对。因为是局部变量,加上优化,keil可能无法解析出正确的地址,所以存在数据不对,完全正常。但是static变量,即使优化,地址都是唯一的。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-5-30 08:48:08 | 显示全部楼层
这个bug Encountered an improper argument 很难受。
回复

使用道具 举报

17

主题

82

回帖

133

积分

初级会员

积分
133
 楼主| 发表于 2024-5-30 09:51:25 | 显示全部楼层
mrjiu 发表于 2024-5-30 00:14
补充说明一下,纯个人理解,并不一定对。因为是局部变量,加上优化,keil可能无法解析出正确的地址,所以存 ...

谢谢。
在网上看到一种说法,是说单片机C语言开发,变量尽量写成全局变量,为了克服局部变量带来的不确定性。
实际的单片机开发确实是这样做的吗?
回复

使用道具 举报

4

主题

58

回帖

70

积分

初级会员

积分
70
发表于 2024-5-30 12:37:13 | 显示全部楼层
可能与51的A寄存器有关系,虽然C语言有严格的大小写.
回复

使用道具 举报

7

主题

146

回帖

167

积分

初级会员

积分
167
发表于 2024-5-31 10:07:26 | 显示全部楼层
Encountered an improper argument  这个BUG 在4.XX上是没有的,
除非4.7的MDK 不支持的芯片,不然我不是不会用KEIL5以上的
回复

使用道具 举报

21

主题

481

回帖

544

积分

金牌会员

积分
544
发表于 2024-5-31 10:39:07 | 显示全部楼层
C51跟标准C还是有区别的,局部变量/函数栈等
回复

使用道具 举报

9

主题

156

回帖

183

积分

初级会员

积分
183
发表于 2024-5-31 17:18:25 | 显示全部楼层
a和b好像是和ACC B寄存器冲突导致的,不太清楚。尽量不使用单个字符的变量
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-28 20:12 , Processed in 0.304307 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表