Re: Удивительное рядом - 2. vsnprintf
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 13.05.16 07:15
Оценка: 7 (2)
Здравствуйте, Dair, Вы писали:

D>std::string formatString(const char* format, ...)

D>Берёт строчку-форматтер в формате printf, при помощи vsnprintf подставляет в неё параметры, отдаёт std::string на выходе.

Кстати. Буфер фиксированного размера? Он адаптируется под конкретный вызов?

Насколько я вижу, в Android NDK торековский stdio. В этом случае, вместо snprintf() полезнее fwopen()+fprintf(), а коллбэк в fwopen() пусть расширяет целевую строку (std::string) на пришедшую порцию. Где-то так:

static int addPortion(void* cookie, const char *portion, int plen) {
  std::string* tp = (std::string*) cookie;
  tp->append(portion, plen);
  return plen;
}

size_t formatString(std::string& target, const char* format, ...) {
  FILE* fw = fwopen(&target, addPortion);
  va_list ap;
  va_start(ap, format);
  size_t ret = vfprintf(fw, format, ap);
  va_end(ap);
  fclose(fw);
  return ret;
}
The God is real, unless declared integer.
Отредактировано 13.05.2016 8:56 netch80 . Предыдущая версия . Еще …
Отредактировано 13.05.2016 7:23 netch80 . Предыдущая версия .
Отредактировано 13.05.2016 7:16 netch80 . Предыдущая версия .
snprintf fwopen torek stdio
Re: Удивительное рядом - 2. vsnprintf
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.05.16 22:30
Оценка: -2
Здравствуйте, Dair, Вы писали:

D>Присказка:

D>Сегодня клиент из Поднебесной пишет, что в некотором месте игра на Android 4 работает, а на 6.0.1 — не работает.
D>...
D>Как править — понятно. Но сам факт.

Ты еще покури на бочке пороха — тоже удивишься
Маньяк Робокряк колесит по городу
Re: Удивительное рядом - 2. vsnprintf
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 13.05.16 06:25
Оценка: 3 (1)
Здравствуйте, Dair, Вы писали:

D>В моём случае в эту функцию отдаётся формат и один строковый параметр. Но в формате нет никакого %s — особенности китайской локализации.

D>Согласно стандарта, функция должна бы просто вернуть строчку-формат, забыв про аргумент.

D>Так и происходит на Android4.


D>В мане пишут:

D>[q]Concerning the return value of snprintf(), SUSv2 and C99 contradict each other: when snprintf() is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. [/b]

Ты вообще заметил, что пишешь о разных вещах? Процитированный кусок это реакция на указатель на целевой буфер, равный NULL, при bufsize==0, а перед этим ты говорил про форматную строку и первый позиционный параметр в varargs.

D>Но на SUSv2 всегда было покласть — это стандарт каких-то толстых юниксов типа Solaris, которые нашей таргет-платформой никогда не были.


SUSv2 был стандартом для всех юниксов, хоть многие и не успели догнать. Ты путаешь с SVID, OSF/1 и тому подобными. Но если ты уж взялся обсуждать случай целевого буфера, равного NULL, то уже начиная с исходного POSIX.1-2001 это явно разрешено в нынешнем виде ("aligned with C99").

D>А на Android6 (на Android5 не проверял, но, вроде, так же как и на 6) vsnprintf(NULL, 0, ...) возвращает 1, и, впоследствии, записывает туда пустую строку (один только 0).


D>Как править — понятно. Но сам факт.


Если ты ничего не попутал, то одновременное нарушение C99 и POSIX это 100% баг, и обязаны вылечить. Но рассказ про отсутствие %s заставляет думать, что тебе надо тщательнее перепроверить свои выводы.
The God is real, unless declared integer.
Отредактировано 13.05.2016 6:28 netch80 . Предыдущая версия .
Удивительное рядом - 2. vsnprintf
От: Dair Россия  
Дата: 12.05.16 22:27
Оценка: 1 (1)
Присказка:
Сегодня клиент из Поднебесной пишет, что в некотором месте игра на Android 4 работает, а на 6.0.1 — не работает.

Полез разбираться.
Взял два Android-телефона, на одном 4.4.2, на другом — 6.
Баг воспроизводится.

Удивительно — думаю я. В конкретно этом месте к OS какой бы то ни было вообще обращений нет. Один и тот же код одинаково работает на iOS, Android, Win32, Win8/10, OS X.

Поскольку у меня нет настроенного окружения для отладки C++ под Android, отлаживаюсь дебажным выводом.


Сказка:

Есть у нас в игре функция общего назначения, используемая и в хвост и в гриву:
std::string formatString(const char* format, ...)


Берёт строчку-форматтер в формате printf, при помощи vsnprintf подставляет в неё параметры, отдаёт std::string на выходе.

В моём случае в эту функцию отдаётся формат и один строковый параметр. Но в формате нет никакого %s — особенности китайской локализации.
Согласно стандарта, функция должна бы просто вернуть строчку-формат, забыв про аргумент.

Так и происходит на Android4.

В мане пишут:
[q]Concerning the return value of snprintf(), SUSv2 and C99 contradict each other: when snprintf() is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. [/b]

Но на SUSv2 всегда было покласть — это стандарт каких-то толстых юниксов типа Solaris, которые нашей таргет-платформой никогда не были.

А на Android6 (на Android5 не проверял, но, вроде, так же как и на 6) vsnprintf(NULL, 0, ...) возвращает 1, и, впоследствии, записывает туда пустую строку (один только 0).


Как править — понятно. Но сам факт.
Re[2]: Удивительное рядом - 2. vsnprintf
От: Dair Россия  
Дата: 12.05.16 22:33
Оценка:
Здравствуйте, Marty, Вы писали:

D>>Как править — понятно. Но сам факт.


M>Ты еще покури на бочке пороха — тоже удивишься


В смысле? Тот, кто писал функцию, полагался на стандарт.
Re[2]: Удивительное рядом - 2. vsnprintf
От: Dair Россия  
Дата: 13.05.16 06:59
Оценка:
Здравствуйте, netch80, Вы писали:

N>Если ты ничего не попутал, то одновременное нарушение C99 и POSIX это 100% баг, и обязаны вылечить. Но рассказ про отсутствие %s заставляет думать, что тебе надо тщательнее перепроверить свои выводы.


ok, у меня пропадает суббота на исследования.

Да, я не знаю, кто виновен — отсутствие форматтера в формате или нули в первых параметрах — итерация "компиляция — инсталляция — запуск" для меня около 5 минут, очень долго.
Re[2]: Удивительное рядом - 2. vsnprintf
От: Dair Россия  
Дата: 13.05.16 07:29
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Dair, Вы писали:


D>>std::string formatString(const char* format, ...)

D>>Берёт строчку-форматтер в формате printf, при помощи vsnprintf подставляет в неё параметры, отдаёт std::string на выходе.

N>Кстати. Буфер фиксированного размера? Он адаптируется под конкретный вызов?

Происходит два вызова vsnprintf. Первый — vsnprintf(NULL, 0, format, ...) — возвращает размер нужного буфера. Этот буфер и выделяется, и в него вызывается второй раз vsnprintf.

N>Насколько я вижу, в Android NDK торековский stdio. В этом случае, вместо snprintf() полезнее fwopen()+fprintf(), а коллбэк в fwopen() пусть расширяет целевую строку (std::string) на пришедшую порцию. Где-то так:


  Скрытый текст
N>
N>static int addPortion(void* cookie, const char *portion, int plen) {
N>  std::string* tp = (std::string*) cookie;
  tp->>append(portion, plen);
N>  return plen;
N>}

N>size_t formatString(std::string& target, const char* format, ...) {
N>  FILE* fw = fwopen(&target, addPortion);
N>  va_list ap;
N>  va_start(ap, format);
N>  size_t ret = fprintf(fw, format, ap);
N>  va_end(ap);
N>  fclose(fw);
N>  return ret;
N>}
N>


Прикольно. Сейчас посмотрю, есть ли такое под виндой и iOS, гугл пока не справился.
Re[3]: Удивительное рядом - 2. vsnprintf
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 13.05.16 08:28
Оценка:
Здравствуйте, Dair, Вы писали:

D>Прикольно. Сейчас посмотрю, есть ли такое под виндой и iOS, гугл пока не справился.


Под виндой — 100% нет — там stdio отстал лет на 30.
Под iOS — вероятно, BSD userland => большие шансы на Torek stdio.
Под Linux (в общем) вместо fwopen — fopencookie и коллбэк чуть другой.
The God is real, unless declared integer.
Re[3]: Удивительное рядом - 2. vsnprintf
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.05.16 20:03
Оценка:
Здравствуйте, Dair, Вы писали:

D>>>Как править — понятно. Но сам факт.


M>>Ты еще покури на бочке пороха — тоже удивишься


D>В смысле? Тот, кто писал функцию, полагался на стандарт.


стандарт не стандарт, а не люблю функции с ...
Маньяк Робокряк колесит по городу
Re: Удивительное рядом - 2. vsnprintf
От: Dair Россия  
Дата: 17.05.16 13:03
Оценка:
продолжил исследование, описал в мобильных устройствах
Автор: Dair
Дата: 17.05.16
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.