Hatred's Log Place

DON'T PANIC!

Nov 19, 2013 - 1 minute read - linux

ps2pdf и отрицательное смещение сверху

Если при преобразовании PS в PDF на выходе наблюдается отрицательное смещение (как бы часть листа срезана) сверху, то стоит попробовать явно задать формат страницы при преобразовании: ps2pdf -sPAPERSIZE=a4 input.ps output.pdf

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

Nov 18, 2013 - 7 minute read - programming c++

Эффект плазмы

Во многих системах есть хранитель экрана который показывает примерно следующее:
-PLASMA-ColorCycling.Gif

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

Nov 9, 2013 - 2 minute read - life

Владивосток: УК "Дальневосточный регион" и смена сантехники

Не вызывайте их сантехников, особено не для аварийных работ, типа смены сантехники /канализация, унитаз/, монтажа разводки:

  • В понедельник будем вызывать заново, т.к. течёт унитаз по эксцентрику, а сегодня ещё обнаружилась течь на месте стыка новой фановой трубы со стоячной. Из-за небольшой лужи, которая образовалась при пробных запусках, после проливки не заметил
  • Разводку делают не аккуратно, про обводы /для обхода труб/ узнал сам из интернет.
  • Не смонтрировали узел с счётчиками до начала кладки плитки /были онформированы/, в результате местер, кто делал ремонт неверно посчитал размер короба, как следствие - результат далёк от ожидаемого.
  • Стоимость при этом достаточно кусачая, и даже примерная смета отличается от списка работ на сайте компании.
  • Наша ошибка, не затребовали составление договора, акт выполненых работ сделан только в одном экземпляре, который, естественно, остался не у нас. Ни компания, ни сами мастера даже не предложили. Смета работ тоже не составлена.
  • Неверно посчитали материалы, как результат пришлось два раза дополнительно бегать покупать /для установки змеевика, унитаза/
  • Не позвали, когда прикручивали змеевик, в результате утопили в короб /ещё не смонтированный/, пришлось просить “выдвигать”, дырки на новом кафеле “приятно” дополняют внешний вид.

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

Ещё один камень в огород: на сайте есть телефон аварийной службы, позвонили им, на что они ответили, что текущая канализация, особенно после новой установки - не аварийный случай, ждите понедельника, а после работы этих сантехников сейчас два стояка /14 квартир/, сидят без холодной и горячей воды, так же до понедельника.

Сайт: http://www.dvregion.vl.ru

Oct 30, 2013 - 1 minute read -

Luakit и Readability.com

Чуть более года назад выложил свои конфиги для Luakit на гиториусе: https://gitorious.org/hatred-configs/luakit/

Помимо подстроек под себя, там же был реализован URI-rewriting. Правда использовал только для хабра, что бы адрес преобразовался по следующему правилу: http://habrahabr.ru/post/196966/ –> http://m.habrahabr.ru/post/196966/

дабы избавится от рекламы, флеша и лишнего форматирования.

Вчера же добавился функционал для сохранения страниц на сервисе отложенного чтения readability.com. Сделано полностью в виде отдельного модуля (в отличии от URI-rewrite). По умолчанию заданы следующие комбинации клавиш:

  • vv - смотреть страницу через readability
  • vs - сохранить для отложенного чтения
  • vg - открыть сайт readability.com в новой вкладке

У функционала “смотреть страницу через readability” внезапно оказалось одно интересное и полезное побочное свойство: просмотр страниц, попавших в немилость роскомнадзору.

Enjoy! :simple_smile:

TODO добавить функционал для открытия сайта через http://anonymouse.org/cgi-bin/anon-www.cgi/URL или:

Oct 21, 2013 - 1 minute read - programming

Big-endian и little-endian: шпаргалка

Big-endian Little-endian
Формулировка Старшие разряды (байты) - первые Младшие разряды (байты) - первые
Запись {{ }} M = \sum{i=0}{n} {A_i} * {B^i} = A_0 * B^0 + A_1 * B^1 + \cdots + A_n * B^n {{ }}
::: {{ }}B{{ }} - база системы счисления, для dec - 10, для hex - 0xFF или 256.

{{ }}A_0{{ }} - младший разряд, {{ }}A_n{{ }} - старший разряд
::: An, …, A1, A0 A0, A1, …, An
::: 1024 (dec), 0x0400 (hex)
dec 1, 2, 0, 4 4, 0, 2, 1
::: hex 0x40, 0x00 0x00, 0x40
Синонимы Network byte order
Motorola byte order
Intel byte order
VAX order
Использование Обычная для человека((Для письма слева-направо)) запись чисел (в том
числе шестнадцатиричных в C/C++ и других)
TCP/IP
PNG
Числа в памяти на x86 и некоторых других
USB
PCI

Oct 4, 2013 - 1 minute read -

Пароль BIOS на ноутбуке Toshiba

Дома настраивал ноутбук Toshiba матери. При включении сразу меня поприветствовала такая надпись:

Первая мысль была сбросить пароль на биос, в поисках подходящего репепта обнаружились следующие сайты:

Но сначала решил попробовать стандартные варианты тыпа qwerty и иже с ними. При этом, после окончания попыток наблюдал такую картинку:

Этот номер меня немного заинтересовал и забил я этой CRC в гугле на поиск. Изыскания привели к этой статье: http://dogber1.blogspot.co.uk/2009/05/table-of-reverse-engineered-bios.html, где рассказывается про алгоритм как получить подходящий пароль, контрольная сумма которого будет такой же как и у неизвестного. Там же в конце идёт ссылка на сайт Вячеслава Бачерикова, который реализовал этот алгоритм на JavaScript:

Первый же пароль от туда подошёл к системе (хотя нотбука и нет среди “поддерживаемых”). Так что даже не пришлось разбрать ноут и сбрасывать настройки CMOS.

Одно не понимаю, нафига все эти защиты, если они обходятся достаточно не сложным анализом и поиском в гугле?

Oct 2, 2013 - 2 minute read - programming c++

На заметку: чисто виртуальные функции с определением

Да, речь про такое:

struct Foo {
  virtual ~Foo()      = 0; // [1]
  virtual void proc() = 0; // [2]
};

// [3]
Foo::~Foo() {
  // some actions
}

// [4]
void Foo::proc() {
  // some actions
}

[3] и [4] для [1] и [2] соответственно могут находится в другом файле.

Информации в интернете много, поэтому заметка для себя, ибо где-то пропустил в изучении. Далее мои домысли и моё понимание проблемы.

Начнём с [2].

Такое нужно: <WRAP center round tip 60%>

  1. когда требуется, что бы в наследниках эти функции были обязательно определены (т.е. были чисто виртуальными в базовом),
  2. но при этом требуется, что бы была предоставлена реализация по умолчанию. Например:
struct Bar : Foo {
  virtual void proc() {
    // здесь полностью своя реализация
  }
};

struct Baz : Foo {
  virtual void proc() {
    // а здесь мы позвали реализацию по умолчанию.
    Foo::proc();
  }
};

struct Bak : Foo {
  // а такой класс мы инстанцировать не сможем
};

А теперь про [1]

Начнём с того, что деструкторы, по иерархии, не переопределяются и при уничтожении объекта вызываются все деструкторы до базового класса и если деструктор будет чисто виртуальным, то получим такую ошибку, ещё на этапе компиляции:

/tmp/cc42YqK5.o: In function `Bar::~Bar()':
main.cpp:(.text._ZN3BarD2Ev[_ZN3BarD5Ev]+0x1f): undefined reference to `Foo::~Foo()'
collect2: error: ld returned 1 exit status

Т.е. тело у деструктора должно быть всегда (ну не совсем, см. ниже). Так когда возникает необходимость сделать деструктор базового класса чисто виртуальным с определением? Мне в голову пришло только: <WRAP center round tip 60%>

  1. сделать класс чисто виртуальным, не объявляя ни одной чисто виртуальной функции.
  2. сделать класс только со статическими членами и запретить создание объектов этого типа, помогает защититься от дружественных классов и функций и просто от наследования (помещение конструктора по умолчанию в приватную секцию не спасёт от френдов). В этом случае, кстати, делать определение для чисто виртуального деструктора не обязательно.

Поясню. Если сделать так:

struct Virtuable {
  virtual ~Virtuable() {}
};

Все классы-наследники автоматом будут с виртуальными деструкторам, но при этом мы можем сделать такое:

Virtuable f;
Virtuable *p = new Virtuable;

Т.е. мы можем создать объекты-пустышки. А зачем нам это? Если же объявить класс так:

struct Virtuable {
  virtual ~Virtuable() = 0;
};

Virtuable::~Virtuable() {}

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

Имхо, может быть полезно во всяких фабриках.

Sep 27, 2013 - 3 minute read - linux

Мысли о DPI

Точнее о DPI((Dots Per Inch [точек на дюйм] - мера разрешающей способности чего либо: монитора, принтера и т.п.)) мониторов.

Очень вяло задавался вопросом, почему на моём маленьком, слабеньком, не сильно дорогом Asus EeePC 1000HA изображение на мониторе отличное, почти все шрифты выглядят нормально, а почти на всех новых, рабочих мониторах с диагональю 24 дюйма и фулхд разрешением, полная беда, что в Linux, что в Windows.

Да, можно покрутить ручки fontconfig или поставить mactype, но всё равно: на нетбуке же я не крутил!

Sep 26, 2013 - 3 minute read - linux

Logitech Unifying и Linux

Кратко: Logitech Unifying Receiver приёмник у беспроводных устройств Logitech к одному которому можно слинковать до 6 устройст. При этом устройство, с которым вместе идёт приёмник уже заранее слинковано с ним и работает из коробки.

Проблема в том, что бы добавить новое устройство. Для этого нужен софт, и софт этот -есть- был только под Windows и под Mac OS X. Хорошо, что слинковав устройства на одном компе можно было использовать их на остальных без проблем. Но, согласитесь, не удобно.

Sep 19, 2013 - 3 minute read - programming c++

Онлайн компиляторы C/C++ и не только

Иногда нужно быстро проверить работоспособность какой-то идеи или алгоритма. Хорошо, когда у вас Linux и какая-то система из семейства Unix с установленным компилятором (имхо, в 90% случаев это будет правдой), вам просто нужно открыть консоль вызвать vim/emacs/joe/mcedit/etc набросать программку и вызвать компилятор. Но иногда вы в гостях/командировке/интернет-кафе, в общем тогда, когда компилятора нет под рукой, но есть доступ в интернет. Тут помогут онлайн-компиляторы.

Sep 18, 2013 - 2 minute read - programming c++

Забавный баг

Есть некая система (embedded), у которой вся память поделена на пулы различного размера и способы выделения память (фиксированный размер, переменный размер). Есть механизм для выделения памяти из этих пулов (на основе размера аллокации подбирает подходящий пул и делает от туда выделение) и возвращение её туда, примем его таким:

void *pool_alloc(size_t size); // выделение памяти из пула
void *pool_calloc(size_t size); // выделение памяти из пула и зануление её
void pool_free(void *ptr); // возврат (освобождение) памяти в пул

есть так же определённые операторы new/new[]/delete/delete[] для использования этого механизма в C++ коде (код сильно упрощён):

void* operator new (size_t size)
{
    return pool_alloc(size);
}

void* operator new[] (size_t size)
{
    return pool_alloc(size);
}

void operator delete (void *ptr)
{
    pool_free(ptr);
}

void operator delete[] (void *ptr)
{
    pool_free(ptr);
}

На этом вводная часть закончена. Переходим к сути.

Существовала испокон веков некая большая структура (в терминологии C++ - POD тип), и код, использующий её был повсеместно на чистом C. Назовём эту структуру так:

struct BigStruct 
{
    // a lot of fields
};

Соответственно память под эту структуру выделялась и освобождалась так:

...
big_struct_ptr = (struct BigStruct*)pool_calloc(sizeof(struct BigStruct)); // память сразу занулялась
...
pool_free(big_struct_ptr);
...

Время шло, код постепенно “переписывался” на C++. В кавычках, потому как это “переписывание” сводилось к изменению расширения файла на .cpp и исправлению очевидных ошибок и предупреждений (тут, с одной стороны, используется -Werror как опция для GCC, с другой стороны, предупреждение включены далеко не все). И вот, в один прекрасный момент, весь код, который использует эту структуру, уже компилируется C++ компилятором. Как результат, при очередной фиче или багофиксе в структуре появляется поле типа

std::vector<Foo> some_field;

То есть, одним мановением руки, структура перестаёт быть POD-типом, но… Механизм выделения и освобождения памяти для неё не меняется!

Теперь сделайте паузу и пофантазируйте, к чему это приводит.

На практике, это решение жило около двух лет (на момент написания статьи) и никак себя не проявляло. А приводило оно к постепенной утечке памяти: для std::vector не вызывался ни конструктор ни деструктор. Отсутствие вызова конструктора проходило незаметно, в этом конкретном примере “спасало” то, что память занулялась и у класса нет vtable. А вот отсутствие вызова деструктора приводило к тому, что все аллокации, сделанные внутри вектора, не освобождались. Маскировало эту проблему то, что аллокации были очень маленькие (около 4 байт), и их было немного за весь период нормальной работы аппарата от момента включения до выключения.

Выявило нагрузочное тестирование, где один алгоритм прогонялся атипичное, для нормальной работы, количество раз (помогло логирование вызовов new при помощи gcc’шной __builtin_return_address(), objdump -d и базовые знания ассемблера).

Sep 10, 2013 - 6 minute read - programming

Qt Creator и perforce

UPD: Изменения, на основе этого патча, заинтегрированы в Qt Creator другим человеком. От меня была только ревью кода.

Во времена, когда проект Qt и все смежные тулы были под управлением VCS Perforce, появился плагин для Qt Creator’а для интеграции работы с этой системой, да вот только в своём развитии он конкретно и застрял в тех стародавних временах. Причина проста: проект переехал на Git, а перфорс нафиг никому не сдался. Как результат: плагин есть, и даже собирается, да вот только считать его хоть малость рабочим… не получается.

May 18, 2013 - 1 minute read -

Небольшой редизайн сайта

Собственно основу можно заметить невооружённым глазом:

  • Убрана большая шапка
  • Убраны большие закруглённые углы

Менее заметные:

  • Большой логотип претерпел некоторый “ребрендинг” (этот логотип предлагается как картинка по умолчанию при репостинге в G+)
  • Сделаны миникопии логотипа под разные размеры, один из них выводится в верхней навигационной строке, другой используется как favicon (теперь видно, что там картинка, а не чёрная клякса, но чёткости так и не получилось добиться)
  • Возвратил стандартный поиск по сайту, потому как гугловский внезапно стал глючить и выдавать пустые ответы (при этом поисковые запросы типа “site:htrd.su ЗАПРОС” работают исправно), разбираться лень, т.к. сам не веб-разработчик и тратить на это время просто жалко (на крайний случай: https://www.google.ru/search?q=site%3Ahtrd.su). Кроме того, это несколько ускорило загрузку страницы.
  • Небольшая косметика правой колонки: убрано лишнее, подкорректированы размеры шрифтов
  • Немного откорректированы шрифты заголовков

Apr 18, 2013 - 2 minute read - programming c++

Build Boost on Windows with MinGW

Чисто заметка, без вдавания в детали.

Для начала нужно поставить MinGW и MSYS.

Сделать это можно двумя путями. Первый, это поставить и то и другое средствами mingw-get-inst: http://sourceforge.net/projects/mingw/files/Installer/mingw-get-inst/

Но там только GCC 4.7.2, а мне нужен был GCC 4.8 (где брать свежие сборки MinGW я уже ранее писал, замечу только, что брать нужно версию с поддержкой threads-posix и dwarf, если вдруг захочется использовать бинарные сборки Qt). MSYS поставил при помощи mingw-get ( http://sourceforge.net/projects/mingw/files/Installer/mingw-get/, а можно и вручную, скачивая и распаковывая файлы отсюда: http://sourceforge.net/projects/mingw/files/MSYS/). Распаковываем его, к примеру, в C:\msys, далее:

cd C:\msys\bin
mingw-get.exe update
mingw-get.exe install msys

После этого MSYS будет расположен в C:\msys\msys\1.0. Если потребуется ещё что-то от msys: mingw-get list вам в помощь.

Далее сборка Boost (у меня 1.53.0).

Распаковываем его, например в D:\boost_1_53_0

Настраиваем пути до компилятора (делаем это из запущенной копии cmd):

set PATH=c:\msys\msys\1.0\bin;c:\mingw\bin;%PATH%

Тут обращаю ваше внимание на один факт, за который разработчикам буста нужно малость по рукам настучать: буст соберётся хорошо только в случае, если MinGW поставлен в C:\MinGW и ни как иначе!

После чего собираем bjam:

cd D:\boost_1_53_0\tools\build\v2
bootstrap.bat gcc
b2 --prefix=C:\boost install
set PATH=%PATH%;C:\boost\bin

Теперь мы готовы собирать сам буст:

cd D:\boost_1_53_0\
bjam -j2 toolset=gcc --build-type=complete --prefix=C:\boost install

Вместо -j2 ставим нужное количество потоков сборки.

После продолжительной сборки буст будет расположен:

  • заголовки: C:\boost\include\boost-1_53
  • библиотеки: C:\boost\lib

И полезные параметры при сборке:

-Wno-unused-local-typedefs -DGLIBCXX_FORCE_NEW -D_WIN32_WINNT=0x0501 -DBOOST_THREAD_USE_LIB -DBOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN

Для совсем ленивых, напоминаю про альтернативную сборку MinGW от Стефана, в ней он уже обновил GCC до 4.8 и Boost до 1.53. Кстати, Стефан работает в Microsoft :)