TechCave

Описание сайта

Основная информация

C++ — компилируемый строго типизированный язык программирования общего назначения. Поддерживает разные парадигмы программирования: процедурную, обобщённую, функциональную; наибольшее внимание уделено поддержке объектно-ориентированного программирования.

Рейтинг: 4
Создана 4 года назад
Владелец root

Стена группы

Загрузка...
2 года назад
#

Жаркая встреча по С++ на Гавайях — Антон Полухин


2 года назад
#

Исключения в Windows x64. Как это работает. Часть 4


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

Описываемый материал требует знания базовых понятий, таких, как пролог, эпилог, кадр функции и понимания базовых процессов, таких, как действия пролога и эпилога, передача параметров функции и возврат результата функции. Если читатель не знаком с вышеперечисленным, то перед прочтением рекомендуется ознакомиться с материалом из первой части данной статьи. Если читатель не знаком со структурами PE образа, которые задействуются в процессе обработки исключения, тогда перед прочтением рекомендуется ознакомиться с материалом из второй части данной статьи. Также, если читатель не знаком с процессом поиска и вызова обработчиков исключений, рекомендуется ознакомиться с третьей частью данной статьи.

Источник
2 года назад
#

Свои потоки ввода-вывода в C++ с помощью std::streambuf


В статье на примерах объясняется, как реализовать поддержку потокового ввода-вывода из стандартной библиотеки (<iostream>) для своих классов.
В тексте статьи будет часто встречаться слово «поток», что означает именно поток ввода-вывода ((i/o)stream), но не поток выполнения (thread). Потоки выполнения в статье не рассматриваются.


Введение


Потоки из стандартной библиотеки — мощный инструмент. Аргументом функции можно указать поток, и это обеспечивает ее универсальность: она может работать как со стандартными файлами (fstream) и консолью (cin/cout), так и с сокетами и COM-портами, если найти соответствующую библиотеку.

Однако не всегда можно найти готовую библиотеку, где подходящий функционал уже реализован, может даже вы разрабатываете собственную библиотеку со своими классами. Тогда возникает задача реализации интерфейса потоков своими силами.

Источник
2 года назад
#

Генератор тестовых данных для C++

image
При unit-тестированиии кода рано или поздно встает вопрос тестовых данных. И если в одном случае достаточно просто несколько жестко зашитых переменных, то в других случаях необходимы сколько-нибудь большие и случайные данные. В управляемом мире нет проблем с генерацией пользовательских типов (взять тот же Autofixture), но мир C++ зачастую вызывает боль и страдание(поправьте меня, если это не так). Не так давно я познакомился с замечательной библиотекой boost::di и под ее влиянием у меня начала созревать идея библиотеки, которая позволила бы C++ программистам генерировать пользовательские типы данных, забитых случайными значаниями, и это не потребовало бы предварительного их описания. Получилось что-то вроде:


struct dummy_member{
    float a;
    int b;
};
struct dummy{
    explicit dummy(dummy_member val, std::string c) : val_(val), c_© {}
private:
    dummy_member val_;
    std::string c_;
};
int main(int argc, char* argv){
    auto d = datagen::random<dummy>();
    return 0;
}

Ссылка на код (https://github.com/ukhegg/datagen). Библиотека header-only,C++14. Всех интересующихся прошу под кат.


Источник
2 года назад
#

Немного о строках в Си, или несколько вариантов оптимизировать неоптимизируемое

Хабра, привет!

Не так давно у со мной произошел довольно-таки интересный инцидент, в котором был замешан один из преподавателей одного колледжа информатики.

Разговор о программировании под Linux медленно перешел к тому, что этот человек стал утверждать, что сложность системного программирования на самом деле сильно преувеличена. Что язык Си прост как спичка, собственно как и ядро Linux (с его слов).

У меня был с собой ноутбук с Linux, на котором присутствовал джентльменский набор утилит для разработки на языке Си (gcc, vim, make, valgrind, gdb). Я уже не помню, какую цель мы тогда перед собой поставили, но через пару минут мой оппонент оказался за этим ноутбуком, полностью готовый решать задачу.

И буквально на первых же строках он допустил серьезную ошибку при аллоцировании памяти под… строку.

char *str = (char *)malloc(sizeof(char) * strlen(buffer));

buffer — стековая переменная, в которую заносились данные с клавиатуры.

Я думаю, определенно найдутся люди, которые спросят: «Разве что-то тут может быть не так?».
Поверьте, может.

А что именно — читайте по катом.

Источник
2 года назад
#

Функциональное программирование и c++ на практике


Функциональное программирование (далее ФП) нынче в моде. Статьи, книги, блоги. На каждой конференции обязательно присутствуют выступления, где люди рассказывают о красоте и удобстве функционального подхода. Я долгое время смотрел в его сторону издалека, но пришла пора попробовать применить его на практике. Прочитав достаточное количество теории и сложив в голове общую картину я решил написать небольшое приложение в функциональном стиле. Так как в данный момент я c++ программист, то буду использовать этот замечательный язык. За основу я возьму код из моей предыдущей статьи, т.е. моим примером будет упрощенная 2Д симуляция физических тел.

Заявление

Я ни в коем случае ни эксперт. Моей целью была попытка понять ФП и область его применения. В статье я шаг за шагом опишу как я превращал ООП код в некое подобие функционального с использованием c++. Из функциональных языков программирования я имел опыт только с Erlang. Другими словами, здесь я опишу процесс своего обучения — возможно, кому-то это поможет. И конечно же я приветствую конструктивную критику и замечания. Даже настаиваю, чтобы вы оставляли комментарии — что я делал неправильно, что можно улучшить.

Введение

В статье я не буду рассказывать теорию ФП — в сети великое множество материала, в том числе и на хабре. Хоть я и старался приблизить программу к чистому ФП, на 100% мне это сделать не удалось. В некоторых случаях из-за нецелесообразности, в некоторых — из-за отсутствия опыта. Так, например, рендер выполнен в привычном ООП стиле. Почему? Потому что одним из принципов ФП является неизменность данных (immutable data) и отсутствие состояния. Но для DirectX (API, который я использую) необходимо хранить буферы, текстуры, устройства. Конечно возможно создавать все заново каждый фрейм, но это будет чертовски долго (о производительности мы поговорим в конце статьи). Еще пример — в ФП часто применяются ленивые вычисления (lazy evaluation). Но я не нашел в программе места для их использования, поэтому их вы не встретите.

Подробнее
Den
2 года назад
#

Красиво «взламываем» ООП с помощью C++14


Вступление

Недавно при работе над проектом учебной практики возникла потребность из своего кода порождать произвольный процесс и одновременно читать его stdout и stderr. Так как приложение пишется исключительно для linux, я решил заодно разобраться с epoll. Для запуска процесса на просторах интернета была найдена маленькая библиотека, делающая как раз то, что нужно, да еще и оборачивающая ввод-вывод в привычные потоки из стандартной библиотеки (речь о ).

Вооружившись несколькими статьями про epoll, я уже было собирался писать код, если бы не одно «но» — для epoll нужен доступ к «сырым» файловым дескрипторам, а автор библиотеки не предоставляет public-доступа к ним. Методы класса, возвращающие дескрипторы, скрыты под грифом «protected».

Что делать?

Самым простым было бы исправить код библиотеки и переместить нужные методы в public-секцию, еще лучше было бы форкнуть библиотеку и реализовать необходимый функционал самому. Но первое было бы некрасиво и сулило бы конфликтами при обновлении библиотеки, а второе заняло бы слишком много времени на разбор кода библиотеки и последующее тестирование под несколькими разными *nix-системами.

Поэтому в голову пришла безумная третья мысль: почему бы не попытаться как-то красиво «взломать» ООП и «легально» получить доступ к protected-методу без вмешательства в исходный код библиотеки? О том, какие преграды возникли на этом пути и как помог C++14 в их преодолении, и пойдет рассказ в данной публикации.

Тестовое окружение

Для примера используем следующий простой код:

#include <iostream>

class A {
protected:
	int f(){ std::cout << "Protected" << std::endl; return 0; }
};

int main(int argc, char **argv){
	A a;
	int val = 1;
	//val = a.f(); // как добраться до f()?
	
	return val;
}

Подробнее
2 года назад
#

О строковом форматировании в современном C++


Доброго времени суток!

В этой статье я хотел бы рассказать о существующих возможностях строкового форматирования в современном C++, показать свои наработки, которые я уже несколько лет использую в реальных проектах, а также сравнить производительность различных подходов к строковому форматированию.

Строковое форматирование — это операция, позволяющая получить результирующую строку из строки-шаблона и набора аргументов. Строка-шаблон содержит текст, в который включены местозаполнители (placeholders), вместо которых подставляются аргументы.

Для наглядности небольшой пример:

int apples = 5;
int oranges = 7;
std::string str = format("I have %d apples and %d oranges, so I have %d fruits", apples, oranges, apples + oranges);
std::cout << str << std::endl;

Здесь:
Строка-шаблон: I have %d apples and %d oranges, so I have %d fruits
Местозаполнители: %d, %d, %d
Аргументы: apples, oranges, apples + oranges

При выполнении примера, получаем результирующую строку

I have 5 apples and 7 oranges, so I have 12 fruits

Теперь посмотрим, что же нам предоставляет C++ для строкового форматирования.

Подробнее
2 года назад
#
Прогресс не стоит на месте: OpenMP 4.5

Прогресс

Всё течет, всё меняется, и OpenMP продолжает активно развиваться. Почти три года назад стандарт стал поддерживать не только параллелизм по задачам, но и по данным (векторизацию), про что я подробно писал. Самое время посмотреть, что появилось в последней версии, выпущенной в ноябре 2015, и что уже поддерживается на данный момент в компиляторах от Intel. Ну что, приступим!

Конструкция taskloop

Рассмотрим некоторый цикл, который мы хотим распараллелить по задачам с помощью OpenMP. Раньше мы бы просто написали директиву parallel for перед ним, и нашли своё счастье. Что-то вроде такого:

#pragma omp parallel for
for (int j = 0; j<n; j++)
  do_useful_job(j);

Но «всё меняется когда приходят они» — новые стандарты и возможности. Теперь появилась возможность не просто отдавать на выполнение всем потокам какие-то куски итераций, а создавать для них задачи (task’и), которые будут распределяться по потокам. Реализуется это с помощью конструкции taskloop:

#pragma omp taskloop

Написав эту директиву перед циклом for, мы тем самым говорим, что итерации этого цикла нужно поделить на куски, и для выполнения каждого из них создать задачу. Далее эти задачи будут выполняться потоками, но при этом нет прямой привязки выполнения какого-то куска итераций конкретным потоком. При этом мы можем контролировать число задач с помощью клаузы num_tasks, а также размер самих кусков через grainsize. Если мы зададим 32 задачи с помощью num_tasks(32), то при числе итераций равном 1024, каждая будет выполнять по 32 итерации цикла. Честно говоря, и в предыдущем стандарте OpenMP 4.0 можно было сделать это:

#pragma omp taskgroup
{
  for (int tmp = 0; tmp < 32; tmp++)
    #pragma omp task
    for (int i = tmp * 32; i < tmp * 32 + 32; i++)
      do_useful_job(i);
}

Подробнее
2 года назад
#
Универсальный конструктор Auto

С приходом C++11 появилась возможность объявлять переменные с типом auto, а компилятор сам определил фактический тип переменной, на основе типа инициализируемого значения. Это удобно, когда мы хотим проинициализировать переменную тип которой слишком сложный, либо неизвестен, либо он нам не очень важен, либо просто для простоты.

Например:

auto f = [](){}; //указатель на функцию
auto r = foo(10); //тип возвращаемый функцией foo
for (auto i = 0; i < 10; i++){} 

… и т.д. То есть в левой части равенства у нас автоматический тип auto, а в правой части значение четко определенного типа. А теперь представим, что у нас все наоборот:

int a = auto(10);

Слева у нас четко описанный тип, а справа что-то неизвестное. Конечно в данном примере нет смысла вызывать универсальный конструктор, когда можно было просто присвоить к переменной a значение 10:

int a = 10;

Или в крайнем случае вызвать его конструктор:

int a(10);

А если это аргумент функции, например:

str::map<char, int> myMap;
myMap.insert(pair<char, int>('a', 10));

Подробнее
2 года назад
#
Умный указатель для начинающих с использованием счетчика

Статья пишется с единственной целью — дать начинающим базовое представление об умных указателях. Я осведомлен в том, что статьи такого рода уже существуют, но они едва ли дают новичку понимание действия данного инструменты. Мне ни в коем случае не хочется журить других авторов, дело только в том, что многие упоминают о самой реализации умного указателя только вскользь, все больше толкуя о существующих инструментах, хронологии их появления, преимуществах и недостатках. Мне же хотелось бы, чтобы студент-первокурсник, делая лабораторную работу, получил готовую и простую реализацию умного указателя с пакетом объяснений в придачу.

Вступление

А начнем мы с начала: в общем случае умный указатель — это некоторая надстройка над обыкновенным указателем, которая добавляет в него полезную или требуемую функциональность. Значит это все то, что он должен предоставлять все те же возможности по работе с указателем (разыменование, получение доступа к полям или функциям из-под указателя) и заниматься «грязной работой» — предотвращать утечки, избегать обращения к ранее освобожденному участку памяти. Хотелось бы сразу сказать, что мне случалось видеть создание объектов умного указателя только для адресов, под которыми лежат объекты классов, что верно, ведь зачистки памяти под указателями подошел бы и обычный MemoryGuard, которому бы хватило одного delete.

Ближе к делу

Итак, перейдем непосредственно к реализации Shared Pointer. Сперва вести учет ресурсов не будем. Требования к классу будут следующие:

— Наличие конструктора, принимающего указатель на ресурс.
— Перегруженные операторы -> и *.
— Акссесор, позволяющий получить адрес ресурса.

Поскольку класс шаблонный, описание и реализацию можно выполнить в одному hpp-файле. Операторы -> и * могут быть определенные как члены класса, ведь слева от них будет всегда находится объект нашего умного указателя.

template<class T>
class shr_ptr
{
        T* resource;
public:
        shr_ptr(T* res=NULL):resource(res)
        {     
        } 
        ~shr_ptr()
        {
                delete resource;
        }
        T* operator ->() const 
        {
                return resource;
        }
        T& operator * () const 
        {
                return *resource;
        }
        T* get () const 
        {
                return resource;
        }
};

Подробнее
Den
2 года назад
#
Реализация блочного шифра «Кузнечик» с режимом CFB на С++

Сегодня речь пойдёт о новом алгоритме блочного шифрования «Кузнечик» из стандарта ГОСТ Р 34.12 2015. В последнее время выходит множество публикаций, посвященных этому стандарту. В них с теоретической точки зрения описываются приведённый алгоритм, изучаются особенности отельных преобразований, а так же предлагаются способы оптимизации, путём включения вставок кода на языке ассемблера.

В данной статье я предлагаю читателю ознакомиться с реализацией данного блочного шифра на языке С++. Стоит отметить, что при написании данной программы не преследовалась цель достичь наибольшей эффективности, а основной задачей было показать, как работает алгоритм. Ознакомиться с описанием алгоритма можно в официальной документации.

Структура программы

Программа состоит из трех частей
  • набор вспомогательных функций и классов — mycrypto.cpp mycrypto.hpp

  • блочный шифр «Кузнечик» — Kuznyechik.cpp Kuznyechik.hpp

  • режим шифрования Cipher Feed Back — modes.hpp


Использованные обозначения

#define BLOCK_LENGTH 16

typedef unsigned char BYTE;
typedef unsigned short WORD;

Вспомогательные средства

Класс ByteBlock
class ByteBlock {
    BYTE * pBlocks;
    size_t amount_of_bytes;
public:
    // Construct block of bytes which contsists of
    // size_ blocks each of them with init_value in it
    ByteBlock(size_t size_ = 0, BYTE init_value = 0);

    // Construct block with size_ first bytes of pBlocks_
    // The value will be copied, source stays untouchable
    ByteBlock(BYTE * pBlocks_, size_t size_);

    // Move constructor
    // Copy constructor thus implicitly deleted
    // Object to move turn to null
    ByteBlock(ByteBlock && rhs);

    // Destructor, yeah
    ~ByteBlock();

    // Move assigment operator
    // Object to move turn to null
    void operator = (ByteBlock && rhs);

    // This cast may be convenient to use the ByteBlock
    // in functions which takes raw pointers as argument
    BYTE * byte_ptr();
    const BYTE * byte_ptr() const;

    // Indexing operator with evident functionality
    BYTE & operator [] (size_t index);
    BYTE operator [] (size_t index) const;

    bool operator == (const ByteBlock & lhs) const;
    bool operator != (const ByteBlock & lhs) const;

    // Replace body of the current block with pBlocks_
    // Old value will be zerod, and then, deleted
    // New value copied into the block,
    // source stays untouchable
    void reset(const BYTE * pBlocks_, size_t size_);

    // Return amount of bytes in block
    size_t size() const;

    // It'll return deep copy of the block, which
    // points to different place in memory
    ByteBlock deep_copy() const;

    // It'll return slice of current ByteBlock
    ByteBlock operator () (size_t begin, size_t length) const;

    // Changes values between two ByteBlock-s
    friend void swap(ByteBlock & lhs, ByteBlock & rhs);
};

Подробнее
2 года назад
#
PVS-Studio для Linux

PVS-studio

Свершилось! Сегодня мы выпустили публичную версию анализатора PVS-Studio для Linux. Теперь разработчики Linux приложений получат новое мощное оружие для борьбы с багами в коде. Призываем разнести эту новость по миру. Расскажите своим коллегам по работе, напишите в Twitter и Facebook! Да будут программы надёжней и стабильней!

Начиная с версии 6.10 анализатор PVS-Studio поддерживает не только Windows, но и Linux платформу.

PVS-Studio выполняет статический анализ кода и генерирует отчёт, помогающий программисту находить и устранять ошибки. PVS-Studio выполняет широкий спектр проверок кода, но наиболее силён в поисках опечаток и последствий неудачного Copy-Paste.

Подробнее
Den
2 года назад
#
Элементы функционального программирования в C++: частичное применение

Не буду сильно углубляться в теорию. Что такое частичное применение легко найти в интернете. В том числе на Википедии.

Если кратко, то это механизм, позволяющий зафиксировать k аргументов функции от n аргументов, сделав из неё функцию от (n — k) аргументов.

// Пусть имеется функция f от четырёх аргументов:
int f (int a, int b, int c, int d)
{
    return a + b + c + d;
}

// Фиксируем первые два аргумента:
auto g = part(f, 1, 2); // 1 + 2 + ...

// Добрасываем оставшиеся два:
assert(g(3, 4) == 10); // ... + 3 + 4 = 10

Подробнее
Den
2 года назад
#
Задачка на std::multiset или поиск по полям структуры

Попалась небольшая задачка, где-то на 4 часа кодирования, которую счел занимательной.

Есть база пользователей 10 миллионов:

class User{
 int id; 
 time_t birthday; // дата рождения
 int gender;      // пол
 int city_id;     // место проживания
 time_t time_reg; // дата регистрации
};

Нужно сделать быстрый поиск по базе, с учетом ее не частого обновления. Поиск может проходить по полям: возрасту, полу, городу. Поля поиска могут быть указаны в группировке или отдельно, например:
  • город;

  • город, пол;

  • пол, возраст.


Данные выдачи должны быть отсортированы по дате регистрации пользователей, и выдаваться постранично по 100 пользователей.

Подсказка 1: СУБД не даст нужной скорости.
Подсказка 2: Вспомнить сложность операций со множествами, сложность стандартных алгоритмов.
Подсказка 3: Проверить время поиска реализованного алгоритма, неплохой результат это порядка 0.005 сек.

Из готовых контейнеров для этой задачи можно использовать std::vector, отсортированный по нужному кретерию поиска, и std::lower_bound с реализацией:

template <class ForwardIterator, class T, class Compare>
  ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
                               const T& val, Compare comp);

Или использовать std::multiset. Выбрал std::multiset по причине того, что в него можно засунуть компаратор, который будет использоваться для вставки и поиска.

Подробнее
9 10 12 13

Авторизация

Войти с помощью

Пользователи

GeekBrains

КАРКАМ

Нетология