Почему я не вижу сброс буфера printf?

У меня есть простая программа (рабочий пример):

#include <unistd.h>
#include <stdio.h>

int main() {
  pid_t my_pid = getpid();
  char str[30];

  sprintf(str, "/proc/%d/fd", my_pid);
  printf("hello, I am gonna print out: %s", str);

  execvp( "ls", (char *[]) { "ls", str, NULL } );

  return 0;
}

скомпилирован с помощью gcc на виртуальной машине Linux. Мой вопрос в том, почему вывод, отправленный на printf, никогда не печатается.

Я понимаю, что printf буферизует свой вывод и сбрасывает только \n. Мне интересно, почему он не печатает в этом случае. Я читал, что потоки вывода сбрасываются при выходе из программы. printf буферизует выходные данные в malloc-й части памяти (я подтвердил это в своей реализации).

Мои вопросы по этому поводу (более подробная информация приветствуется):

  • Почему закомментирование вызова execvp приводит к тому, что вывод печатается на stdout, но не печатается как есть? Я думаю, не будет ли это считаться завершением программы даже после того, как ls каннибализирует процесс?
  • Будет ли буфер printf в памяти считаться выходным потоком?
  • Совершенно не связанная с этим вопросом деталь: мне интересно, почему дескриптор файла 10 на zsh и 255 на bash не наследуются моим процессом.

Или, другими словами: буферизованные данные хранятся в памяти, локальной по отношению к старому процессу, но поскольку этот полностью заменяется новым, прежний перестает существовать, прежде чем он сможет очистить буфер. Память об этом либо отбрасывается, либо повторно используется (перезаписывается) новым процессом.

Aconcagua 18.04.2023 08:32

"не будет ли это по-прежнему считаться выходом из программы" Нет.

n. m. 18.04.2023 11:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
2
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

execvp заменяет старый процесс новым процессом. Все открытые файловые дескрипторы остаются открытыми, но данные, буферизованные библиотекой C stdio, не сохраняются. Код запуска C прикрепит новый указатель FILE к файловому дескриптору STDOUT. Ключевым моментом является то, что файловый дескриптор является объектом ОС, тогда как указатель FILE является объектом библиотеки C. Сохраняется только объект ОС.

Соответствует ли FILE* буферизованной памяти (как в printf)? Почему необходимо иметь и FILE*, и файловый дескриптор? Если я закрою дескриптор файла STDOUT_FILENO, должен ли я ожидать, что FILE* stdout перестанет работать?

user129393192 11.05.2023 07:02

Другие вопросы по теме