Theos 处理 logos 代码的 bug 分析

之前在编译一个 tweak 时,死活编译不过。今天终于找到原因了

先说结论:.x 和 .xm 后缀名文件,如果单行块注释中包含 // 会导致编译失败。单行块注释中 // 后面的内容也会被 Theos 当注释处理

如何解决:使用多行块注释,或者行注释,或者在 // 中间插入空格

用最小代码重现这个 bug,文件保存为 main.x 或 main.xm,代码如下

代码 1

#include <stdio.h>

/* https://iosre.com/ */
int main() {
    /* Hello world! */
    printf("Hello world!\n");
    return 0;
}

make 编译,报错

main.x:8: error: fell off the face of the planet when we found a '}'

问题就出在第一个注释,如果单行块注释中包含 // 就会出现这个 bug

代码 2

#include <stdio.h>

/* https://iosre.com/ */
int main() {
    printf("Hello world!\n");
    return 0;
}

代码 2 可以编译,但链接失败找不到 _main 符号

logos 预编译生成的 main.x.m 文件,很明显注释后面的代码都当注释处理了

#line 1 "main.x"
#include <stdio.h>

猜想

    #include <stdio.h>

//  |-- 这是块注释
//  |
//  |        |-- 这被当成了注释的注释(实际上没有注释的注释这种说法)
//  |        |
    /* https://iosre.com/ */
    int main() {
        printf("Hello world!\n");
        return 0;
    }

代码 1 的等效代码。第一个注释的 /* 和第二个块注释的 */ 组成了匹配

#include <stdio.h>

/* https:
int main() {
    /* Hello world! */
    printf("Hello world!\n");
    return 0;
}

代码 2 的等效代码。/* 注释掉了后面所有代码,所以链接失败找不到 _main 符号

#include <stdio.h>

/* https:
int main() {
    printf("Hello world!\n");
    return 0;
}

等效代码编译报错和前面一样。

结案。

4 个赞

点赞,最近干货分享越来越少了。
估计就是编译器前端切token的时候搞了点bug出来。

是的。这个问题纠结了一个月的时间,我都怀疑人生了。今天总算找到原因了。

翻了一下logos的源码,perl写的,语法好晦涩。看代码不是挨个scan token,而是用正则先把单行注释给删了?

卤煮有心的话,搞一下,去提个issue。然后提个pr,给社区做点贡献。

image

2 个赞

看了一眼这个1000行的文件之后,突然产生了一种我也能造出来这种轮子的错觉。。。。。。。。。。。 :see_no_evil:

之前提过另外一个小bug的pr然而并没有回应,好像没人管了 :rofl:

:+1: 看来是先处理了行注释引起的这个问题。我会去提一个 issue