Как правильно использовать _vsnprintf_r()?

Я пытаюсь узнать что-то о повторных вызовах и пытаюсь использовать _vsnprintf_r(). Первый параметр кажется каким-то struct _reent *. На Cygwin кажется, что я мог бы просто использовать это так: _vsnprintf_r (_REENT, /* rest of the arguments here */). Это правильно? Это правильно даже за пределами Cygwin? Кажется, для этого не хватает документации. Мои поиски в Google и Bing были не слишком плодотворны.


person wilx    schedule 15.06.2012    source источник
comment
Такой функции, вероятно, нет ни на одной другой платформе. Ведущий _ обычно является знаком, который говорит, что не трогайте меня, если вы не взламываете саму библиотеку C.   -  person Fred Foo    schedule 15.06.2012
comment
Это не способ узнать о повторных вызовах. Это способ узнать об уродливой внутренней реализации cygwin. Если вы думаете о написании реализации стандартной библиотеки, было бы полезно прочитать исходный код cygwin (вероятно, как представление о том, что нельзя делать при написании собственной), но если вы просто хотите чтобы узнать о написании реентерабельного кода, это тривиально просто: не используйте неконстантные статические/глобальные переменные.   -  person R.. GitHub STOP HELPING ICE    schedule 15.06.2012
comment
Известно ли, что у vsnprintf когда-либо была рентрантная версия? Это означало бы, что он модифицирует общий ресурс (массив символов назначения). Вызовы vsnprintf находятся между va_start() и va_end(). Связанная тема обсуждения: stackoverflow.com/questions/3865713 /is-va-start-etc-reentrant   -  person Arvind    schedule 15.06.2012


Ответы (2)


_vsnprintf_r не является стандартной функцией. Он был создан командой разработчиков cygwin для внутреннего использования.

_vsnprintf_r вызывается обычным vsnprintf, поэтому я бы придерживался обычной версии C этого вызова на cygwin. Cygwin не гарантирует, что _vsnprintf_r в любом случае является реентерабельным, особенно если вы не можете найти документацию об этом.

Поскольку cygwin использует динамически загружаемую библиотеку, которая имеет общее состояние между всеми процессами, которые связываются с ней, он использует _<xxx>_r версии вызовов, чтобы дать каждому процессу свои собственные экземпляры состояния, которые обычно используются по умолчанию в стандартной системе UNIX. Поскольку эти функции используются cygwin для внутреннего использования, вы можете найти список рассылки cygwin-developers лучшим ресурс для вашего вопроса.

Это отличается от реентерабельных функций, определенных POSIX (например, gmtime_r). Нереентерабельные версии этих возвращенных указателей на статическую память в библиотеке, поэтому реентерабельные версии были созданы, чтобы позволить функции вместо этого использовать память, переданную вызывающей стороной.

person jxh    schedule 15.06.2012
comment
Предположим, что у меня есть причины не использовать не _r версию. - person wilx; 15.06.2012
comment
@wilx: Достаточно честно! Я отредактировал ответ, предложив список рассылки cygwin-developers в качестве лучшего ресурса. Спасибо и привет. - person jxh; 15.06.2012

Вы, вероятно, не хотите ничего «печатать» с повторными вызовами, потому что вы не знаете, в каком порядке или когда что-то будет «печатать».

В общих чертах, чтобы писать реентерабельные функции, передайте в функцию все (без статических переменных). Локальные (стековые) переменные в порядке, насколько я знаю.

Печать — «классическая» проблема для семафоров (или какого-либо другого механизма блокировки). В противном случае,

Привет, мир

становится

HeWlorllod

или в лучшем случае

HellWorldo

person Josh    schedule 15.06.2012
comment
Реентерабельность немного отличается от параллелизма с потоками. - person wilx; 15.06.2012