scanf генерирует segfault, когда программа запускается с пользовательской точкой входа (используя gcc 7.4.0) - PullRequest
11 голосов
/ 04 июня 2019

Рассмотрим следующий код:

#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("main\n");
    int a;
    scanf("%d", &a);
    printf("a = %d\n", a);
    return 0;
}

int main1() {
    printf("main1\n");
    int a;
    scanf("%d", &a);
    printf("a = %d\n", a);
    exit(0);
    return 0;
}

int main2() {
    printf("main2\n");
    int a = getchar() - '0';
    int b = getchar() - '0';
    int c = getchar() - '0';
    printf("a = %d\n", 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

Но если я заменю scanf тремя getchars, программа снова будет работать нормально, несмотря на то, чтозапустить с пользовательской точкой входа:

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

Чтобы сделать вещи еще более интересными, эти проблемы возникают с gcc 7.4.0, но не с gcc 4.8.4.

Есть идеи?

1 Ответ

12 голосов
/ 04 июня 2019

Флаг командной строки -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 »» от компоновщика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...