*** ВНИМАНИЕ: Блог переехал на другой адрес - demin.ws ***

воскресенье, 20 июня 2010 г.

fill_n vs memset

В данный момент на текущей работе я занимаюсь тем, что называется - высокоуровневое серверное программирование на С++. У меня уже есть все необходимые библиотеки низкого уровня и среднего (более того, если я отказываюсь по какой-то причине от готовой библиотеки, меня могут потом попросить это объяснить), и огромное количество библиотек высокого уровня, уровня бизнес-логики. К чему все это?

А вот к чему. Если разобраться, что я могу писать код вообще без С-шных штучек типа массивов, malloc/free, старого способа приведения типов, строчек с нулем на конце и т.д. Получается, что мой диалект С++ можно урезать на тему всего, что я перечислил. Просто убрать, и все.

И от этого будет только польза. Сколько ошибок потенциально я НЕ сделаю в арифметике указателей (ее просто не будет)? Вместо того, чтобы мотивировать человека "разумно использовать наследия С в С++", их надо просто выключить. Конечно, сразу сузится и круг решаемых задач, но мой, кстати, не самый узкий круг, можно покрыть таким вот урезанным в сторону "правильного" С++ диалектом С++.

Например, как мне кажется, функция memset() в мире С++ в целом годится разве что для обнуления. Использование какой-либо иной константы-заполнителя принципиально приближает нас к проблемам с памятью. Хотите, например, "эффективно" заполнить строку пробелами, и зарядите для этого memset(), а потом вам неожиданно придется работать с многобайтовыми кодировками, и этот пробел, записанный через memset(), может стать источником проблем.

Так что используйте алгоритм "fill_n()" вместо "memset()". Может быть неэффективен? Может, а может и нет. Зато уж точно безопасен с точки зрения типизации.

13 комментариев:

  1. Верная позиция. Всегда нужно писать рабочий код, а не задумываться над оптимизацией/быстродействием. А штучки C++ (не Си) помогают писать код с меньшим кол-вом ошибок и меньшим кол-вом строк кода. Об оптимизации потом скажет профайлинг. :)

    ОтветитьУдалить
  2. Александр, а зачем тогда использовать С++?
    После такого урезания получается джава с очень медленным компилятором и без сборки мусора.
    А если еще и смарт-поинтером пользоваться, то и почти со сборкой мусора.
    Но:
    1. нет нормальной среды программирования, в которой можно было бы делать рефакторинг, как в IDEA/Eclipse на джаве
    2. нет нормальных тулов для проверки быстродействия - требуют значительной "перекомпиляции"
    3. медленный компилятор
    4. из-за отсутствия run-time class-inspection и reflection тяжело делать мощную автоматизацию проверок.

    Все эти вещи можно простить, когда нужны низкоуровневые штуки С. Если они не нужны - нет ни какой необходимости писать на С++ вообще.

    ОтветитьУдалить
  3. Согласен с Nick по всем пунктам, кроме третьего: нормальные "тулы для проверки быстродействия" есть, и если слова vtune, valgrind и oprofile не известны, то писать на C++ просто не нужно.

    ОтветитьУдалить
  4. С fill_n и memset другая проблема. И тому и тому можно по ошибке задать диапазон, выходящий за пределы контейнера, который мы чистим, и перетереть кучу. А потом через много-много строчек кода разбираться, почему у нас exception на выделении/освобождении памяти.

    ОтветитьУдалить
  5. Зачем Java? Если уж речь зашла о managed environments, то тогда уж C# (Mono, если не Windows). Гораздо более красивый, развитый и наглядный язык как таковой.

    Кстати, о рефакторинге. В видео про язык Go (см. предыдущий пост), авторы критикуют ООП языки типа C++/Java/C#/etc именно за болезнь рефакторинга. Если ты вдруг захотел потрогать базовые класса, вот и начинается массовый рефакторинг.

    ОтветитьУдалить
  6. @ilja.golshtein: К сожалению, мы пользуемя только valgrind и он на порядок хуже тулов для джавы.
    В нашем проекте, например, есть проблема скалабилити и ухудшения перформанса при заметном увеличении нагрузки. Так вот, при запуске с valgrind он падает от "перегрузки" на 20% от нагрузки которую тянет без valgrinda. И мало чего находит. А свой собственный фреймоворк, без инструментаций - находит.
    Про другие тулы - спасибо, поизучаю.
    @Александр: рефакторинг это не только перелопачивание иерархии классов. Даже переименовывание в С++ поддерживается всякими IDEs с грехом пополам. Video не смотрел пока, нельзя найти время на все, но моя собственная практика говорит мне, что без рефакторинга ни как. И мне тяжело поверить, что есть другая парадигма, где рефакторинг будет не нужен.

    ОтветитьУдалить
  7. @Nick: Если рассматривать сложности с рефакторингом с чисто технической стороны, типа переименовать класс, убрать/добавить параметоры метода и т.д., то лично я полностью не согласен, что какое-либо IDE может радикально ускорить процесс. Я сейчас попеременно работаю в Eclipse для C++ и VIM с плагином NERD_tree. Не могу сказать, что в эклипсе я что-то делаю радикально быстрее, чем в VIM. То есть это просто вопрос, насколько хорошо освоен инструмент. То есть если я переименовал базовый класс, то пока не починю все дочерние классы, то просто проект не соберется. И врядли я тут могу ошибок наделать. А вот вопрос того, что мне впринципе надо зачем-либо трогать базовый класс только ради переименования, и почему это затрагивает остальные классы - это уже вопрос к ООП парадигме как таковой.

    ОтветитьУдалить
  8. Хорошо, когда просят обосновать отказ от библиотеки.
    Я встречался только с ситуациями, когда наоборот.

    ОтветитьУдалить
  9. Этот комментарий был удален автором.

    ОтветитьУдалить
  10. Потроллить что-ли :-)

    А вот Линус Торвальдс утверждает, что C++ и все, что с ним связано, - sucks. И что лучше он будет писать с указателями и прочими радостями жизни=)

    http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918

    ОтветитьУдалить
  11. Да, Линуса сложно упрекнуть, что он никогда не работал со сложными и большими проектами, которые длятся годами, работают на множестве архитектур и требуют постоянного развития и поддержки ;-).

    ОтветитьУдалить
  12. Мне очень понравилась у него фраза

    Quite frankly, even if the choice of C were to do *nothing* but keep the C++ programmers out, that in itself would be a huge reason to use C.

    Тем не менее, такие проблемы надо решать как-то по-другому.

    ОтветитьУдалить
  13. /**
    * @brief Fills the range [first,first+n) with copies of value.
    * @ingroup mutating_algorithms
    * @param first An output iterator.
    * @param n The count of copies to perform.
    * @param value A reference-to-const of arbitrary type.
    * @return The iterator at first+n.
    *
    * This function fills a range with copies of the same value. For char
    * types filling contiguous areas of memory, this becomes an inline call
    * to @c memset or @ wmemset.
    */

    http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01032_source.html

    ОтветитьУдалить