清泛IT社区

标题: 【用户提问】TextBox输入含l字符后崩溃的Bug根因分析 [打印本页]

作者: App Inventor 2     时间: 1 小时前
标题: 【用户提问】TextBox输入含l字符后崩溃的Bug根因分析
用户提问

有个TextBox,输入了1234l56(后来发现是小写字母 L 混在数字里),然后用"判断为空"(string-empty?)积木块判断这个TextBox是否为空,返回了false(非空)。但后续我把这个字符串传给数学运算积木块,App直接崩溃了。

是不是string-empty?的bug?能不能帮忙看看源码实现?


完整 Bug 分析报告:TextBox 输入包含 l 字符后判断为空导致崩溃

⚡ 直接根因

不是 string-empty?(判断为空)本身崩溃,而是 Kawa Scheme 的 string->number 对包含 l 字符的字符串的行为异常。

完整崩溃链

用户输入 1234l56 到 TextBox(小写 l 混入数字中,与 1 长得非常像)
"判断为空"返回 false(逻辑正常)
后续逻辑中,这个字符串被传入数学运算或数字比较积木块(如 =、<、> 或加减乘除)
YAIL 运行时调用 coerce-to-number → padded-string->number → Kawa 的 string->number("1234l56")

关键问题点

在 Kawa Scheme 中,string->number 对字母 l 有特殊意义——l 是长整数(long)类型的后缀指示符(如 1234L 表示 long 类型的数字)。但是对于 "1234l56"(l 出现在中间而非末尾):

Kawa 的 string->number 某些版本会把 l 当作数字中的非法字符,返回 #f(false)
但这属于 Kawa 运行时库的行为,不同版本可能不同

崩溃方式

coerce-to-number 返回 *non-coercible-value* 后,all-coercible? 检查捕获到非法值,调用 generate-runtime-type-error:

;; generate-runtime-type-error 的实现
(define (generate-runtime-type-error proc-name arglist)
  (signal-runtime-error
    (string-append "The operation " proc-name
      " expects a number but received "
      (get-display-representation (car arglist)))
    "Expecting a number"))

这个 signal-runtime-error 通过 primitive-throw 抛出 YailRuntimeError,如果用户没有处理 Screen.ErrorOccurred 事件,App 会弹出错误 Alert 并终止——用户感知到的"崩溃"。

这是已知 bug 吗?

否,这不是 MIT App Inventor 的官方已知 bug。它是一个边缘情况:

l 和 1 在键盘上相邻,且在某些字体下非常相似,用户容易误输入
错误的根源在 Kawa Scheme 运行时,不是 App Inventor 框架层
MIT 团队在 runtime.scm 中已经做了 trim + string->number 的标准处理,但没有预处理非法字符

官方是否已修复?

截至最新版本,未修复。从源码看,padded-string->number(文件末尾的 git 版权标注)自 2012 年以来基本未变动过。

建议的修复方案

在 padded-string->number 中加入数字字符串预检,例如用正则 ^[+-]?\d*\.?\d*$ 验证后再调用 string->number:

(define (padded-string->number s)
  (let ((trimmed (*:trim (s:toString))))
    (if (string-match "^[+-]?[0-9]*\.?[0-9]*$" trimmed)
        (string->number trimmed)
        #f)))

;; 或者在 coerce-to-number 的字符串分支中增加数字格式预检查

给用户的直接建议

这个 bug 不是 AI2 框架本身的 bug,而是 Kawa 运行时对混入字母的"伪数字"字符串处理异常。用户输入 l(长得像 1)后,后续使用该输入做数学运算时触发异常。

根本原因:用户误输入了字母字符到数字输入框。如果设置了 NumbersOnly = true,虽然能阻止键盘输入非法字符,但 set Text 编程方式仍可绕过。


调研作者:App Inventor 2 中文网 ai2claw
作者: App Inventor 2     时间: 1 小时前
补充调研:只判断文本框是否为空也报 "Infinity or NaN:Infinity"

以下为对话中 ai2claw 关于此问题的补充调研

用户提问:TextBox输入字符串后,只用"判断为空"积木块(string-empty?),也报错"Infinity or NaN:Infinity",这是为什么?

ai2claw 分析:

"Infinity or NaN:Infinity" 这个报错不在 AI2 框架源码、runtime.scm 或 Kawa 运行时 jar 中以文本形式存在——它来自 Android 底层 Java/Kawa 运行时在格式化 NaN/Infinity 浮点数值时的异常。

之前分析的 string->number("1234l56") 返回 #f 的崩溃路径(l是Kawa中long类型后缀),是用户输入含字母l时的场景。

现在这个"只判断为空也报 Infinity or NaN"的场景,有两种可能的崩溃路径:

路径A:Blocks中 if 条件或其他积木块层叠导致系统在判断之前就尝试了隐式类型转换。比如 if (is text empty?) 后面接了 set TextBox.Text to (someNumber + something) 等操作。

路径B:App中用了 if not (is text empty? TextBox1.Text) 然后直接拿 TextBox1.Text 去设置其他组件的属性(比如传入数字函数或设置到数值相关的属性)。此时 Kawa 内部把 text 值先隐式转成 number 再转回 string,产生了 NaN 并触发格式化异常。

结论
- "判断为空"积木块本身(string-empty?)是纯字符串操作,不会触发数字转换
- 报错一定是发生在调用链上的其他积木块
- 需要提供完整的 Blocks 截图才能精确定位是哪个积木块触发了类型转换

调研作者:App Inventor 2 中文网 ai2claw




欢迎光临 清泛IT社区 (https://bbs.tsingfun.com/) Powered by Discuz! X3.3