Re[3]: sprintf и надежность программы
От: korzhik Россия  
Дата: 24.08.04 07:42
Оценка: 3 (1)
Здравствуйте, Basil2, Вы писали:

B>Решил остаться на sprintf, заменив ее на _snprintf и подключив проверку типов.


Вот ещё здесь почитай.
Re: sprintf и надежность программы
От: Аноним  
Дата: 18.08.04 09:19
Оценка: +1
Здравствуйте, Basil2, Вы писали:

B>Есть

B>Консольная Win32-программа (Сервер). Программа активно протоколирует свою работу (и шлет свои состояния по сети) с помощью ф-ции sprintf. Однако,

B>Проблема

B>Были случаи, когда программа выпадала именно на этой ф-ции. Например, если указываю "%s %d", а по ошибке передаю "PktNumber, ClnName" (т.е. в обратном порядке). Ну и банальные переполнения буфера и NULL'ы, плюс проблема если в данных встречается символ '%'... Дополнительная сложность в том, что некоторые sprintf'ы отвечают за ошибки, и, соответственно, исполняются (или валят программу) когда эти ошибки происходят — воспроизвести же все ошибки при тестировании не всегда представляется возможным (XP-шную идею тестов изучил совсем недавно). Отсюда,

B>Вопрос

B>Как красиво решить проблемы с надежностью? При этом, крайне желательно:

B>- сохранить простоту вызова ф-ции форматирования (а'ля вызов ОДНОЙ ф-ции)

B>- не использовать внешние библиотеки (MFC, в частности)
B>- корректная работа ф-ции, если она получила в кач-ве параметра NULL или указатель на память вне программы (тут, я понимаю, надо как-то отлавливать Memory read access error)
B>- использовать компилятор MS VC 6.0, но иметь совместимость с BCB и Watcom.

B>Полазив по форуму, я нашел _sNprintf, она решает проблему буфера, но не решает проблему NULL и перепутанного порядка аргументов (тут в программе менял формат протоколирования: переделал более 200 операторов sprintf — мрак какой-то! ).

B>Еще вариант "cout << Data", но это не очень удобно и нужен вывод именно в строку, а не в консоль. Какие есть варианты?!

B>P.S. Как говориться, рассмотрю любые предложения!


Ну попробуйте покапать в сторону boost::format

Там примерно такое использование:

boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50;
"writing toto, x=40.230 : 50-th try"

Касательно NULL и прочих memory read access violation — в нашей жизни мало счастья — делайте обертки __try{}__except(){}

Можно попробовать их автоматизировать как-нибудь. (Вспомогательная функция, макросы).

Совметимость из той же серии BCB — ограниченая, Watcom просто не помню. Посмотрите boost документацию.
Re: sprintf и надежность программы
От: Кодт Россия  
Дата: 18.08.04 10:15
Оценка: +1
Здравствуйте, Basil2, Вы писали:

B>Еще вариант "cout << Data", но это не очень удобно и нужен вывод именно в строку, а не в консоль. Какие есть варианты?!


std::ostringstream ost;

ost << "Hello" << 123;

std::string s = ost.str();
Перекуём баги на фичи!
Re: sprintf и надежность программы
От: moudrick Россия http://community.moudrick.net/
Дата: 18.08.04 10:52
Оценка: +1
B>Еще вариант "cout << Data", но это не очень удобно и нужен вывод именно в строку, а не в консоль. Какие есть варианты?!

а что, stringstream не рулит?
#include <sstream>

http://www.cplusplus.com/ref/iostream/stringstream/

B>P.S. Как говориться, рассмотрю любые предложения!
sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 18.08.04 09:07
Оценка:
Есть
Консольная Win32-программа (Сервер). Программа активно протоколирует свою работу (и шлет свои состояния по сети) с помощью ф-ции sprintf. Однако,

Проблема
Были случаи, когда программа выпадала именно на этой ф-ции. Например, если указываю "%s %d", а по ошибке передаю "PktNumber, ClnName" (т.е. в обратном порядке). Ну и банальные переполнения буфера и NULL'ы, плюс проблема если в данных встречается символ '%'... Дополнительная сложность в том, что некоторые sprintf'ы отвечают за ошибки, и, соответственно, исполняются (или валят программу) когда эти ошибки происходят — воспроизвести же все ошибки при тестировании не всегда представляется возможным (XP-шную идею тестов изучил совсем недавно). Отсюда,

Вопрос
Как красиво решить проблемы с надежностью? При этом, крайне желательно:

— сохранить простоту вызова ф-ции форматирования (а'ля вызов ОДНОЙ ф-ции)
— не использовать внешние библиотеки (MFC, в частности)
— корректная работа ф-ции, если она получила в кач-ве параметра NULL или указатель на память вне программы (тут, я понимаю, надо как-то отлавливать Memory read access error)
— использовать компилятор MS VC 6.0, но иметь совместимость с BCB и Watcom.

Полазив по форуму, я нашел _sNprintf, она решает проблему буфера, но не решает проблему NULL и перепутанного порядка аргументов (тут в программе менял формат протоколирования: переделал более 200 операторов sprintf — мрак какой-то! ).
Еще вариант "cout << Data", но это не очень удобно и нужен вывод именно в строку, а не в консоль. Какие есть варианты?!

P.S. Как говориться, рассмотрю любые предложения!
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re: sprintf и надежность программы
От: korzhik Россия  
Дата: 18.08.04 09:11
Оценка:
Здравствуйте, Basil2, Вы писали:

почитай здесь
Re: sprintf и надежность программы
От: unrealalex Россия  
Дата: 18.08.04 09:19
Оценка:
B>Вопрос
B>Как красиво решить проблемы с надежностью? При этом, крайне желательно:
boost::format

B>- сохранить простоту вызова ф-ции форматирования (а'ля вызов ОДНОЙ ф-ции)

ну почти

B>- не использовать внешние библиотеки (MFC, в частности)

к сожалению, внешняя.... хотя для кого как

B>- корректная работа ф-ции, если она получила в кач-ве параметра NULL или указатель на память вне программы (тут, я понимаю, надо как-то отлавливать Memory read access error)

try{}catch(...) или SEH, но ИМХО пусть лучше в таком случае упадет, все равно в 99% дальнейшая работа программы не будет правильной.

B>- использовать компилятор MS VC 6.0, но иметь совместимость с BCB и Watcom.

врать не буду — не помню... проверить не на чем
Невозможное мы сделаем сегодня — чудо займет немного больше времени. /Аноним/
Re[2]: sprintf и надежность программы
От: Аноним  
Дата: 18.08.04 09:22
Оценка:
Здравствуйте, unrealalex, Вы писали:

Я честно не списывал

Наши посты пришли примерно в 1 время

B>>Вопрос

B>>Как красиво решить проблемы с надежностью? При этом, крайне желательно:
U>boost::format

B>>- сохранить простоту вызова ф-ции форматирования (а'ля вызов ОДНОЙ ф-ции)

U>ну почти

B>>- не использовать внешние библиотеки (MFC, в частности)

U>к сожалению, внешняя.... хотя для кого как

B>>- корректная работа ф-ции, если она получила в кач-ве параметра NULL или указатель на память вне программы (тут, я понимаю, надо как-то отлавливать Memory read access error)

U>try{}catch(...) или SEH, но ИМХО пусть лучше в таком случае упадет, все равно в 99% дальнейшая работа программы не будет правильной.

B>>- использовать компилятор MS VC 6.0, но иметь совместимость с BCB и Watcom.

U>врать не буду — не помню... проверить не на чем
Re: sprintf и надежность программы
От: Vamp Россия  
Дата: 18.08.04 09:44
Оценка:
строковые буфера?
Да здравствует мыло душистое и веревка пушистая.
Re[2]: sprintf и надежность программы
От: Vamp Россия  
Дата: 18.08.04 09:47
Оценка:
Т.е. строковые потоки.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 23.08.04 13:40
Оценка:
Здравствуйте, unrealalex, Вы писали:

B>>- корректная работа ф-ции, если она получила в кач-ве параметра NULL или указатель на память вне программы (тут, я понимаю, надо как-то отлавливать Memory read access error)


U>try{}catch(...) или SEH, но ИМХО пусть лучше в таком случае упадет, все равно в 99% дальнейшая работа программы не будет правильной.


У меня try/catch не ловят read access error, все равно программа вываливается с "instruction XXX accessed address YYY". Пробовал на Watcom 11 и MSVC 6.0. В чем может быть дело? Есть ли работающий пример?
(так, чтобы при конструкции printf("%s", NULL) я мог ее обработать, а не вываливаться из программы)
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[2]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 23.08.04 13:46
Оценка:
Здравствуйте, korzhik, Вы писали:

K>почитай здесь


Огромное спасибо, статью прочитал с большим интересом. Решил остаться на sprintf, заменив ее на _snprintf и подключив проверку типов. У меня к тебе особый вопрос: ты использовал Lint? Конкретно, меня интересует следующее. Он умеет, встретив ф-цию printf, сопоставить строку "%s %d %c" и типы передаваемых аргументов. НО — это, ИМХО, работает только для стандартных ф-ций (*printf). Моя же ф-ция, которая отвечает за это, называется Add (это метод класса LOG), и Lint ее не контролирует. Вопрос — можно ли настроить его или другую программу так, чтобы она проверяла printf-спецификаторы в пользовательских ф-циях?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[3]: sprintf и надежность программы
От: korzhik Россия  
Дата: 23.08.04 13:53
Оценка:
Здравствуйте, Basil2, Вы писали:

B>У меня к тебе особый вопрос: ты использовал Lint?

первый раз слышу.
А что это такое?
Re[4]: sprintf и надежность программы
От: LaptevVV Россия  
Дата: 23.08.04 14:27
Оценка:
Здравствуйте, korzhik, Вы писали:

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


B>>У меня к тебе особый вопрос: ты использовал Lint?

K>первый раз слышу.
K>А что это такое?
Это программа-синтаксический анализатор, выявляющая сомнительные конструкции в программе.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: sprintf и надежность программы
От: LaptevVV Россия  
Дата: 23.08.04 14:31
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Вопрос

B>Как красиво решить проблемы с надежностью? При этом, крайне желательно:

B>- сохранить простоту вызова ф-ции форматирования (а'ля вызов ОДНОЙ ф-ции)

B>- не использовать внешние библиотеки (MFC, в частности)
B>- корректная работа ф-ции, если она получила в кач-ве параметра NULL или указатель на память вне программы (тут, я понимаю, надо как-то отлавливать Memory read access error)
B>- использовать компилятор MS VC 6.0, но иметь совместимость с BCB и Watcom.

Строковые потоки.

Как пишет Страуструп, поток можно прикрепить не к файлу, а к строке. Таким образом, появляется возможность использовать механизм форматирования ввода/вывода для работы со строками. Все делается точно так же, как и с файлами, только надо использовать другие потоки. Система ввода/вывода предоставляет три вида строковых потоков:
istringstream — входные потоки;
ostringstream — выходные потоки;
stringstream — двунаправленные потоки;
Прописаны они в заголовке sstream. Чаще всего используются выходные строковые потоки — для формирования строки, предназначенной для вывода в файл или на экран. Напишем простую функцию, формирующую в строку комплексное число (листинг 6.23).

//Листинг 6.23. Комплексное число –> в строковый поток
struct Complex { double re, im; };
string toString(const Complex &c) 
{    ostringstream os;
    os << '<' << setprecision(3) << re(c) << ‘+’ 
           << setprecision(3) << im(c) << ‘i>’;
    return os.str();
}
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: sprintf и надежность программы
От: 0xVLD  
Дата: 24.08.04 09:02
Оценка:
Здравствуйте, Basil2, Вы писали:

B>У меня try/catch не ловят read access error, все равно программа вываливается с "instruction XXX accessed address YYY". Пробовал на Watcom 11 и MSVC 6.0. В чем может быть дело? Есть ли работающий пример?

B>(так, чтобы при конструкции printf("%s", NULL) я мог ее обработать, а не вываливаться из программы)

Попробуй установить свой фильтр необработанных исключений через SetUnhandledExceptionFilter
Re[4]: sprintf и надежность программы
От: MShura  
Дата: 24.08.04 10:30
Оценка:
Здравствуйте, korzhik, Вы писали:

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


B>>У меня к тебе особый вопрос: ты использовал Lint?

K>первый раз слышу.
K>А что это такое?

Между прочим MS использует эту программу для проверки своих сорсов.
По крайней мере в "свободных" исходниках есть много следов от Lint.
Re[4]: sprintf и надежность программы
От: 0xVLD  
Дата: 24.08.04 10:30
Оценка:
Здравствуйте, 0xVLD, Вы писали:

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


B>>У меня try/catch не ловят read access error, все равно программа вываливается с "instruction XXX accessed address YYY". Пробовал на Watcom 11 и MSVC 6.0. В чем может быть дело? Есть ли работающий пример?

B>>(так, чтобы при конструкции printf("%s", NULL) я мог ее обработать, а не вываливаться из программы)

VLD>Попробуй установить свой фильтр необработанных исключений через SetUnhandledExceptionFilter

(это если на все и вся сразу, чтобы вообще не падала)

Если места точно известны, то можно просто

try
{
     *(PBYTE) 0 = 0;
    printf("%s", NULL);//у меня тут вообще нет ошибки
}
catch (...) 
{
 ::MessageBox(NULL,"ZZZZ","PPPPP",MB_OK);
}



__try
{
     *(PBYTE) 0 = 0;
    printf("%s", NULL);
}
__except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) 
{
  ::MessageBox(NULL,"ZZZZ","PPPPP",MB_OK);

}


если второй вариант надо через try/catch то надо написать класс-обертку EXCEPTION_RECORD и отлавливать его в catch ()
Re[5]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 24.08.04 12:07
Оценка:
B>>>У меня try/catch не ловят read access error, все равно программа вываливается

VLD>Если места точно известны, то можно просто

VLD>
VLD>try
VLD>catch (...) 

VLD>__try
VLD>__except (EXCEPTION_ACCESS_VIOLATION == GetExceptionCode()) 
VLD>


Большое спасибо! Попробовал:
__try / __except работает (ага!), но try/catch нет.

VLD>если второй вариант надо через try/catch то надо написать класс-обертку EXCEPTION_RECORD и отлавливать его в catch ()

Тут я совсем ничего не понял. Мне казалось, что catch(...) ловит все! Разве не так? (какая именно ошибка мне не важно)
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[6]: sprintf и надежность программы
От: 0xVLD  
Дата: 24.08.04 13:25
Оценка:
Здравствуйте, Basil2, Вы писали:


B>Большое спасибо! Попробовал:

B>__try / __except работает (ага!), но try/catch нет.

VLD>>если второй вариант надо через try/catch то надо написать класс-обертку EXCEPTION_RECORD и отлавливать его в catch ()

B>Тут я совсем ничего не понял. Мне казалось, что catch(...) ловит все! Разве не так? (какая именно ошибка мне не важно)

У меня(VS .NET и VS6 на WinXP) — catch (...) все вроде бы ловит.
Вообще, по-моему catch(...) — это майкрософтовская фишка.
Re[7]: sprintf и надежность программы
От: denisku Россия  
Дата: 24.08.04 13:31
Оценка:
Здравствуйте, 0xVLD, Вы писали:

VLD>Вообще, по-моему catch(...) — это майкрософтовская фишка.

нет, это стандартная вещь.
Извините за потраченный траффик..
Re[5]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 24.08.04 14:13
Оценка:
VLD>>Попробуй установить свой фильтр необработанных исключений через SetUnhandledExceptionFilter
VLD>(это если на все и вся сразу, чтобы вообще не падала)

Попробовал, но почему-то вызов циклится. Использую следующий код:

LONG __stdcall MyExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
   printf( "Exception, code is %x, flags %x!\n",
           ExceptionInfo->ExceptionRecord->ExceptionCode,
           ExceptionInfo->ExceptionRecord->ExceptionFlags );
   logMain.Add(PR_HI, "ERROR Exception!");

   if (! ExceptionInfo->ExceptionRecord->ExceptionFlags) // continuable
      return EXCEPTION_CONTINUE_EXECUTION;
   else
      return EXCEPTION_EXECUTE_HANDLER;
}

void main()
{
   SetUnhandledExceptionFilter(MyExceptionFilter);
   *(PBYTE) 0 = 0;
   printf("end");
}


Выход получается такой:

Exception, code is c0000005, flags 0!
Exception, code is c0000005, flags 0!
Exception, code is c0000005, flags 0!
Exception, code is c0000005, flags 0!
Exception, code is c0000005, flags 0!


(c0000005 — access violation)
Почему так может быть?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[7]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 24.08.04 14:24
Оценка:
B>>Большое спасибо! Попробовал:
B>>__try / __except работает (ага!), но try/catch нет.

VLD>У меня(VS .NET и VS6 на WinXP) — catch (...) все вроде бы ловит.


Это я виноват — я компилирую из командной строки, и у меня не был указан ключ /EHa — обработка C++ исключений. С ним все отлично работает!
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[6]: sprintf и надежность программы
От: 0xVLD  
Дата: 25.08.04 11:51
Оценка:
Здравствуйте, Basil2, Вы писали:


B>Почему так может быть?


Потому что выполнение продолжается с той же самой инструкции.

При EXCEPTION_CONTINUE_EXECUTION надо что-то делать для устранения ошибки, либо написать код, чтобы возобновлять выполнение со следующей инструкции.
Re[7]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 25.08.04 12:51
Оценка:
Здравствуйте, 0xVLD, Вы писали:

VLD>Потому что выполнение продолжается с той же самой инструкции.

VLD>При EXCEPTION_CONTINUE_EXECUTION надо что-то делать для устранения ошибки, либо написать код, чтобы возобновлять выполнение со следующей инструкции.

А это вообще реально написать? Как?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[8]: sprintf и надежность программы
От: 0xVLD  
Дата: 26.08.04 13:27
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Здравствуйте, 0xVLD, Вы писали:


VLD>>Потому что выполнение продолжается с той же самой инструкции.

VLD>>При EXCEPTION_CONTINUE_EXECUTION надо что-то делать для устранения ошибки, либо написать код, чтобы возобновлять выполнение со следующей инструкции.

B>А это вообще реально написать? Как?


Можно все в отдельных потоках запускать и завершать поток при возникновении исключения, при необходимости запускать новый.

Можно попытаться изменить информацию об исключении. Скажем, адрес инструкции в которой возникло исключение.
Re[9]: sprintf и надежность программы
От: Basil2 Россия https://starostin.msk.ru
Дата: 27.08.04 07:26
Оценка:
Здравствуйте, 0xVLD, Вы писали:

VLD>>>Потому что выполнение продолжается с той же самой инструкции.

VLD>>>При EXCEPTION_CONTINUE_EXECUTION надо что-то делать для устранения ошибки, либо написать код, чтобы возобновлять выполнение со следующей инструкции.

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


А как это (хоть приблизительно) делается? Как я узнаю, на сколько байтов надо сдвинуть указатель вперед? (размер сбойной команды)
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.