Как понять перекрестную ссылку glibc?

Я пытаюсь понять, как работает программа hello world:

#include <stdio.h>

int main(int argc, char **argv) {
    printf("Hello World!");
    return 0;
}

По большей части это просто, за исключением части printf. Я не знаю, как это работает. Чтобы понять это, я поискал перекрестная ссылка glibc и нашел эту страницу.

Затем я поискал printf и получил много результатов.

Какой из этих printfs моя программа использует? Как я могу это определить?

Кроме того, например, при открытии первого результата на этой странице, функция в функции printf приводит меня к __printf_chk, где функция в __printf_chk приводит меня к __nldbl___vfprintf_chk, где функция в __nldbl___vfprintf_chk приводит меня к __ vfprintf_chk, где функция в __vfprintf_chk снова приводит меня к __ nldbl___vfprintf_chk, что создает бесконечную рекурсию. В чем дело?

Короче говоря, как я должен отслеживать источник данной функции / исходного кода?


person Utku    schedule 18.11.2015    source источник
comment
Какую из этих printfs использует моя программа? Как я могу это определить? Вы должны выяснить, как построена библиотека. Это в основном зависит от того, как вызывается компилятор, который определен в Makefiles. Которые, вероятно, так же нечитабельны. Разве glibc не забава? (Спойлер: glibc - это не весело.)   -  person    schedule 18.11.2015
comment
Еще один спойлер: в конечном итоге вы попадете в определение vfprintf в stdio -common / vfprintf.c, но чтобы увидеть взаимосвязь между этим и такими функциями, как __printf, вам придется продираться через большое количество макросов препроцессора и объявлений атрибутов, специфичных для GCC.   -  person    schedule 18.11.2015
comment
@Rhymoid Причина всего этого в создании / сохранении переносимости?   -  person Utku    schedule 18.11.2015
comment
Я не могу сказать наверняка, но вот мое предположение: есть одна общая реализация, которая абсолютно переносима, а затем есть некоторые корректировки для оптимизации для конкретной платформы (эти __nldbl функции кажутся связанными с системами которые имеют long double). Чтобы это решение оставалось поддерживаемым, существует некоторый уровень макросов и функций-оберток. Со временем этот слой разросся и превратился в бремя обслуживания. (К сожалению, такие сценарии довольно распространены в разработке программного обеспечения.)   -  person    schedule 18.11.2015
comment
@ Рифмоид, я вижу. Тогда, возможно, было бы лучше найти реализацию стандартной библиотеки с открытым исходным кодом, которая была бы намного более легкой.   -  person Utku    schedule 18.11.2015
comment
Хорошо известные альтернативы включают musl, uClibc и dietlibc, по сравнению с glibc, здесь.   -  person    schedule 18.11.2015


Ответы (2)


У меня нет полного ответа, но я не могу оставить комментарий. Похоже, что __vfprintf_chk вызывает vfprintf, который, похоже, имеет псевдоним _IO_vfprintf_internal в /stdio-common/vfprintf.c. Я не знаю происхождения последней функции, но я не вижу здесь бесконечного цикла?

person tauroid    schedule 18.11.2015
comment
На этой странице __vfprintf_chk звонки __nldbl___vfprintf_chk. - person Utku; 18.11.2015
comment
Я понимаю что ты имеешь ввиду. Похоже, я не сильно помогу, и я не знаю, как разрешается упомянутая вами рекурсия, но printf, похоже, определен здесь. Чтобы выяснить, какой из них используется, потребуется копаться в том, какой из них компилируется / компилируется системой сборки, не знаю больше. - person tauroid; 18.11.2015

Реализация printf находится в stdio-common/printf.c

int
__printf (const char *format, ...)
{
   va_list arg;
   int done;

   va_start (arg, format);
   done = vfprintf (stdout, format, arg);
   va_end (arg);

   return done;
}

который вызывает vfprintf

person rohit89    schedule 18.11.2015
comment
Откуда мне знать, что он вызывает тот printf, а не другие? - person Utku; 18.11.2015
comment
Это основная часть, которая меня смущает. Например, когда вы ищете vfprintf на странице перекрестных ссылок, вы получаете около десятка результатов где 3 из них указаны как определения функций. Ваша ссылка указывает на определение 2-й функции среди этих результатов, но как я должен знать, что вызывается 2-й vprintf, а не 2 других? - person Utku; 18.11.2015
comment
Нет простого правила - вам, возможно, придется проверять каждый вариант. glibc довольно плотный из-за требований переносимости и совместимости. Тем не менее, простой способ отсеять некоторые параметры - это посмотреть на пути к файлам и имена файлов. __printf_chk перенесет вас в каталог sysdep - вам не нужно заходить в эти типы каталогов для основных реализаций. - person rohit89; 18.11.2015