Страниц: 1 2 [3]
  Печать  
Автор Тема: Массив строк и PtListAddItems  (Прочитано 19594 раз)
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #30 : Марта 13, 2011, 02:27:46 pm »

Откровенно скажу - незнаю о степени ламерства "оптимизатора". Однозначно можно сказать только то, что он "заболел оптимизацией на ранней стадии проектирования". Я уже описывал 2 реальных случая, когда такая "ранняя оптимизация" мешала дальнейшей полезной оптимизации (статический массив при распараллеливании) и когда такая "оптимизация" приводила к одновременному крашу всех клиентов (попытка отобразить в массив с фиксированным размером строку размер которой гарантироваться кодом не может, аля описанное тут
Код:
sprintf(cdg_str, "%d\t%02d/%02d/%02d %02d:%02d:%02d\t%02d/%02d/%02d %02d:%02d:%02d\n",
reg_range_cdg->num,
            reg_start_tm.tm_mday, reg_start_tm.tm_mon+1, reg_start_tm.tm_year + 1900,
               reg_start_tm.tm_hour, reg_start_tm.tm_min, reg_start_tm.tm_sec,
            reg_end_tm.tm_mday, reg_end_tm.tm_mon+1, reg_end_tm.tm_year + 1900,
               reg_end_tm.tm_hour, reg_end_tm.tm_min, reg_end_tm.tm_sec);
)

У Вас наверное есть обратные случаи, когда "неоптимальный код" крашил приложение? Хотелось бы примеры не далеко от упомянутой темы ("неоптимльные std::string" vs "оптимальны char []")..
Записан
oder
Гость
« Ответ #31 : Марта 13, 2011, 09:19:43 pm »

Ну здесь же ни одной строки в формате нет - одни целые числа. Максимальное количество знаков в целом числе можно определить в глобальном хидере на подобии FLT_DIG/DBL_DIG из <limits.h> (сейчас оно, обычно, - 10). Там же можно поставить асерт, что размер int, всё ещё, не более четырёх байт.
Строку формата из кода убрать, конечно, и огласить через #define. Там же, следуюцим #define описать выражение максимального возможного размера буфера, исходя из количества %d.  Оба дефайна сгруппировать вместе, а сверху и снизу отделить пустыми строками.
Всё! Если разработчик не полный кретин, он, меняя DATETIME_FORMAT_LINE, не может не обратить внимание, что следующей строкой стоит DATETIME_FORMAT_MAXSIZE.
А больных кретинизмом нечего к исходнику подпускать вообще.

Неоптимальный код не может крашить приложение по определению. Он может только приводить к тому, что приложение начнёт работать неприемлимо медленно. А это - эквивалентно крешу, ибо нет разницы из-за чего программой нельзя пользоваться.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #32 : Марта 14, 2011, 01:01:42 am »

Да здравствуют "пляски с бубнами" Smiley.

И такой ерундой заниматься каждый раз при добавлении очередного аргумента.
Или не дай Бог случайно вставят пробел/любой-полезно-читаемый-текс в строку форматирования.
Неожиданно, вдруг, окажется что ассертить нужно не только int..
Smiley.
И это всего лишь при попытке вывести данные фиксированной длины (не утруждайтесь в объяснениях на вывод %s ).
Так и напрашивается вопрос - сколько людей может разделять/сопровождают код который так "с оптимизирован"?
Толи дело заюзать std::string/std::stringstream и забыть вообще про дефайны/длины/размеры/выделение-освобождение руками (и о да, возможно он сожрет/и потом почти сразу же после использования автоматически освободит лишних 100 - 200 байт используя в худшем случае память кучи).

Ваше решение, повысить безопасность кода - ничего толком не поменяло. При дальнейшем расширении/сопровождении код остается опасным.
Желаю удачи людям сопровождающим сей "чудо-код".

Цитировать
Неоптимальный код не может крашить приложение по определению. Он может только приводить к тому, что приложение начнёт работать неприемлимо медленно. А это - эквивалентно крешу, ибо нет разницы из-за чего программой нельзя пользоваться.

Надеюсь вы понимаете что ключевое слова здесь "..Он МОЖЕТ ТОЛЬКО  приводить к тому что приложение начнёт работать неприемлимо медленно". А значит почти в 99% случаях это произойдет только если, изначальные требования были неконкретизированы или нарушены условия работы.
Вы можете долго гордится в одиночестве, утверждая что Ваш проект может запускатся одновременно в 20 экземплярах, умалчивая что он падает с вероятностью 0.001, и это ничто по сравнению с проектом, который удовлетворительно работает и в 5 экземплярах, но незначительно медленне (может быть и ест ресурсов больше), хотя и 5 экземпляров не требовалось изначально (и с ресурсами не критично).
Только вот такой "медленный" проект сравнительно быстро можно "подстроить" под более жесткие требования если потребуется за сравнительно короткое время, а вот избавится от вероятности падения - еще и не факт что так быстро (дай бог чтобы оптимизация на оптимизации не оказалась, да и не дай Бог исправлять это будет тот кто не поймет таких чудесных плясок с дефайнами и не наплодит своих)

« Последнее редактирование: Марта 14, 2011, 01:10:21 am от lastcross » Записан
detsnu
Участник
*
Offline Offline

Сообщений: 17


Просмотр профиля
« Ответ #33 : Марта 15, 2011, 12:49:54 am »

Блин, ну чего пристали к человеку. Бог с ней со скоростью, далеко не всегда это имеет решающее значение. Но вот уж чего не отнимешь у printf-семейства - это наглядности! Именно это меня часто останавливает от соблазна заюзать stringstream или какой-нить другой stream там где они совершенно не к месту. Согласитесь, что вот такой кусок кода:

Код:
    int a;
    float b;
    char buf[32];
    snprintf( buf, sizeof buf, "%02d\t%.4f", a, b );

просто понятнее и нагляднее такого вот аналога

Код:
    int a;
    float b;
    std::stringstream out;
    out   << setfill('0') << setw(2) << a
            << '\t'
            << fixed << setprecision(4) << b
            << ends;

В данном примере с printf достаточно очевидно, что получится на выходе. Так как используется snprintf, есть уверенность, что буфер никогда не будет переполнен. При выводе в поток все гораздо более запутанно. Код слишком перегружен шелухой. Зато все очень безопасно...

Я ни в коем случае никого не агитирую всегда использовать printf'ы вместо стрингов. Но имхо в примерах типа приведенных выше printf является лучшим решением, т.к. на порядок проще и нагляднее. Зачем плодить сложность там где ее нет?

Да, printf потенциально опасен. Но опасен весь язык C/C++ со всеми своими ссылками/указателями и динамической памятью. Всю эту силу надо использовать аккуратно и продуманно. На собственном опыте неоднократно убеждался, что бездумное использование возможностей C++ несет больше вреда, чем пользы.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #34 : Марта 26, 2013, 04:56:52 pm »

Я сразу прошу прощения за "внезапное" поднятие темы из глубин Smiley
Но может быть кому окажется полезным ссылка https://github.com/c42f/tinyformat
Я так же допускаю, что для большинства - она окажется жутким "боянищем", или вроде порождающей эмоции аля "а чем boost не угодил-то?". Но я так же допускаю что найдется пару (десятков Smiley )человек, которым ни весь boost ни его "потрошение" не нужно для решения одного типа задач, которым так близко форматирование printf и дорога безопасность вызова, а быстродействие - вторично (хотя судя по таблице в ссылке не так все и медленно).

З.Ы.: Тема всплыла когда на очередном проекте на стороне сервера потребовалось вставить много логов. Система логов опиралась на вызов printf-подобных методов для формирование строк. Нашлось пару ошибок аля
Код:
std::string someStr;
//....
_log_printf("some log %s", someStr);
//
Стало страшно за сервер и его стабильность в рантайме..
Записан
oder
Гость
« Ответ #35 : Марта 26, 2013, 11:15:58 pm »

Мне компилятор варнинг пишет, если я в printf класс запихиваю. Что я делаю не так?
Записан
oder
Гость
« Ответ #36 : Марта 26, 2013, 11:23:39 pm »

Код:
// Begin of test.cpp
#include <stddef.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>

int main()
{
std::string s = "foo bar";
return printf("%s\n", s);
}

$ g++ -c -Wall -o tetst.o test.cpp
test.cpp: In function 'int main()':
test.cpp:9:25: error: cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'
test.cpp:9:25: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'std::string {aka std::basic_string<char>}' [-Wformat]
$
Записан
detsnu
Участник
*
Offline Offline

Сообщений: 17


Просмотр профиля
« Ответ #37 : Марта 26, 2013, 11:58:17 pm »

Может, он просто хочет видеть
Код:
return printf("%s\n", s.c_str());
?
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 224


Просмотр профиля
« Ответ #38 : Марта 27, 2013, 12:57:56 am »

Мне компилятор варнинг пишет, если я в printf класс запихиваю. Что я делаю не так?

Насколько я понял речь про cstdio-шный printf - хм .. оценил долю иронии )). Я уже писал, что у меня нет в планах подымать повторно тему о "безопасности". Кому интересно будет тот возможно попользуется библой - кому неинтересно, значит не судьба.

А так да, весьма вероятно что для большинства компиляторов может стоять своя "затычка" в виде варнинга для printf-а (и тд. и тп.) и в частности использования в них объектов не POD-типа (которым является std::string). А ведь может и не стоять - и даже внятных варнингов не будет (как например в MVS2005/2012)!. И вообще гарантия POD-типа в качестве аргумента функции, не делает printf-безопасной Smiley. В случае же предлагаемой библы - данной проблемы вообще не возникнет (, а использование случайного POD тип у которого не определен operator << вообще выдаст ошибку компиляции - независимо от типа компилятора)
Записан
Страниц: 1 2 [3]
  Печать  
 
Перейти в: