C - 当程序使用自定义入口点运行时(使用 GCC 7.4.0),SCANF 会产生段错误



请考虑以下代码:

#include <stdio.h>
#include <stdlib.h>
int main() {
    printf("mainn");
    int a;
    scanf("%d", &a);
    printf("a = %dn", a);
    return 0;
}
int main1() {
    printf("main1n");
    int a;
    scanf("%d", &a);
    printf("a = %dn", a);
    exit(0);
    return 0;
}
int main2() {
    printf("main2n");
    int a = getchar() - '0';
    int b = getchar() - '0';
    int c = getchar() - '0';
    printf("a = %dn", 100 * a + 10 * b + c);
    exit(0);
    return 0;
}

假设代码驻留在名为test.c的文件中,则以下内容工作正常(它打印"a = 123"(:

gcc -o test test.c
echo 123 | ./test

但是,如果我使用自定义入口点运行程序,则会出现可怕的分段错误:

gcc -o test test.c -e"main1"
echo 123 | ./test

但是,如果我用三个 getchar 替换 scanf,尽管使用自定义入口点运行,但程序再次运行良好:

gcc -o test test.c -e"main2"
echo 123 | ./test

更有趣的是,这些问题发生在 gcc 7.4.0 中,而不是在 gcc 4.8.4 中。

有什么想法吗?

-e命令行标志重新定义了程序的实际入口点,而不是"用户"入口点。默认情况下,将GCC与GNU C标准库(glibc(一起使用时,此入口点称为_start,它在调用用户提供的main函数之前执行进一步的设置。

如果要替换此入口点并继续使用 glibc,则需要自己执行进一步的设置。但是,您也可以使用以下方法来替换main入口点,这要简单得多:

gcc -c test.c
objcopy --redefine-sym main1=main test.o
gcc -o test test.o

请注意,这仅在在代码中定义main时才有效,否则您将从链接器收到"'main'的多重定义"错误。

最新更新