Сюрприз от Installd

Вчера мне Installd сюрприз сделал. Конечно, можно сказать что нужно внимательнее читать документацию, но, всей документации не перечитаешь, поэтому сюрпризы не избежны. А суть сюрприза вот в чем.
Возникла задача следующего плана: надо взять приложение A, выпилить из него часть функций, воткнуть новые и в результате получить приложение B. Причем, приложения A и B должны уметь работать параллельно. Каждое из приложений содержит в себе драйвера, демоны и кучу других системных компонентов. Таким образом, на диске, получаем приблизительно такую структуру:

/-- Library
    +--Application Suport
        +-- Company Name
            +--Product A
            +--Product B

Где Product B – директория с системными файлами нового приложения. С учетом того, что инсталляторы в Mac OS X воспринимаются исключительно как автоматизированное средство для копирования файлов, решение было предельно простым: взять уже имеющийся инсталлятор и поменять в нем “Product A” на “Product B”, не забыв поправить конфигурирующие скрипты. Но не тут то было.
Если попытаться установить два продукта параллельно, то начиналась магия: установка продукта A деинсталлировала продукт B и vice versa. Перерыл все логи инсталлятора, греша на pred- и post- install скрипты – ни малейшего намека на то, кто удаляет продукт. Хотел уже было браться за DTrace, но тут коллеги напомнили о fs_usage… Нашелся виновник: installd. Но, казалось бы, причем тут Installd?! А вот при том, что инсталлятор не только распаковывает файлы в нужные директории, но еще и делает “обновление” для пакетов с одинаковыми идентификаторами!

RB-tree в sglib

Наткнулся на довольно мерзкий баг, в когда-то уважаемой мной библиотеке sglib. Дело в том, что на определенных наборах данных у rb-tree из этой библиотеки сносит башню! В результате добавленные ранее элементы перестают находиться, хотя, количество элементов не изменяется и при обходе дерева все элементы в нем присутствуют.

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include "sglib.h"

struct rb_tree
{
    int64_t data;
    char color_field;
    struct rb_tree *left;
    struct rb_tree *right;
};
typedef struct rb_tree rb_tree;

#define CMPARATOR(x,y) ((x->data)-(y->data))

SGLIB_DEFINE_RBTREE_PROTOTYPES(rb_tree, left, right, color_field, CMPARATOR);
SGLIB_DEFINE_RBTREE_FUNCTIONS(rb_tree, left, right, color_field, CMPARATOR);

rb_tree *the_tree = 0;

int main(int argc, char *argv[])
{
    if( argc < 2 )
        return -1;

    const char *data_file_path = argv[1];
    FILE *data_file;
    data_file = fopen( data_file_path, "r" );
    if( 0 == data_file )
        return -1;

    uint64_t value;
    rb_tree *node, e;
    e.data = 6610223104;
    int added = 0;
    while( EOF != fscanf( data_file, "%llun", &value ) )
    {
        if( value == e.data )
            added = 1;
        node = malloc( sizeof(rb_tree) );
        node->data = value;
        sglib_rb_tree_add( &the_tree, node );
        if( 0 != added )
        {
            node = sglib_rb_tree_find_member( the_tree, &e );
            if( 0 == node )
                printf("ERRORn");
        }
    }

    return 0;
}

Файл с тестовыми данными.

Лучшее описание C++11

Существует довольно много статей посвященных C++11, которые в той или иной степени описывают вкусности из нового стандарта. Да что там говорить, на той же Википедии существует огромная, и вроде даже хорошая, статья посвященная C++11. Но, как известно, везде и всегда что-то не так…
Так вот, нашел я полностью устраивающее меня описание в виде презентации от Alex Sinyakov, за что ему огромное спасибо!

Кроссплатформенность в современном мире

Очередное обсуждение недостатков Nemerle на РСДНе навело меня на интересную мысль о связи между успешностью того или иного инструмента и его кроссплатформенностью.
По большому счету, Nemerle это язык с интересными концепциями и идеями, который не нужен практически никому, кроме его разработчиков. Почему я делаю такое утверждение? Тут все просто, возьмем для сравнения его ровесников Scala, Groovy и даже совсем молодежь Clojure. Для того что бы понять, нужен ли язык кому-то, кроме его авторов, можно воспользоваться следующей информацией:

  1. На каких языках присутствует информацию о языке в Википедии
  2. На какой строчке находится язык в индексе TIOBE;
  3. Участвует ли язык в индексах The Computer Language Benchmarks Game;
  4. Написал ли кто-то книги по этому языку.

Continue reading

Когнитивный диссонанс

Вчера я был поражен на столько, что усомнился в том, во что верил уже лет 10. А именно в том, что при выравнивании 8, размер структур с полями {u64, u32, u16} и {u8, u32, u16} будет одинаков, т.е. равен 16. А ведь приложение собранное Rust утверждает что в первом случае размер 16, что и следовало ожидать, а во втором 12(!!!).

type tuple_type1 = (u64, u32, u16);
type tuple_type2 = (u8, u32, u16);

fn main() {
    io::println(#fmt("size of tuple_type1 = %u, size of tuple_type2 = %u",
        sys::size_of::<tuple_type1>(), sys::size_of::<tuple_type2>()));
    io::println(#fmt("align of tuple_type1 = %u, align of tuple_type2 = %u",
        sys::align_of::<tuple_type1>(), sys::align_of::<tuple_type2>()));
}

Содержимое консоли:

> ./main
size of tuple_type1 = 16, size of tuple_type2 = 12
align of tuple_type1 = 8, align of tuple_type2 = 8

Continue reading

Миф о Java

Про языки с автоматическим управлением памятью в целом и про Java в частности существует один довольно забавный миф – приложения с автоматическим управлением памяти не текут или текут редко. Бугагашеньки.

Берем известное и крайне популярное среди Java-разарботчиков приложение Intellij IDEA. Открываем в этом приложении большой проект (на мелком не так в глаза бросается) и работаем. Ближе к концу второго-третьего дня работы приложения, объем используемой памяти вырастает с изначальных 300 мегабайт до 700 и IDEA начинает ощутимо тормозить. Полагаю, что дальше будет только больше, лично мне на 700 это дело надоело, и я перезапустил приложение.

Что вобщем-то и требовалось доказать, напортачить можно даже на том языке, где создатели выдали тебе специальный не снимаемый памперс – было бы желание.

using namespace std

В кругах разработчиков C++ периодически возникает спор на тему “почему нельзя/нужно использовать using namespace std“. Наткнулся на довольно показательный пример того, почему этого делать ни в коем случае нельзя.
Товарищ пытается написать удаление пробелов из строки:

#include <iostream>

#include <string>

using namespace std;

int main(int argc, char* argv[]) {
    string str = "";
    cin >> str;
    remove(str.begin(), str.end(), ' ');
    cout << str;
    cin.ignore();
}

и получет довольно неожиданную ошибку компиляции.

'remove': function does not take 3 arguments (C2660)

А все почему? Да потому-что никогда, ни при каких условиях, не надо давать символам из пространства std глобальную видимость! Ведь в данном случае, можно было получить куда более понятное “error: ‘remove’ was not declared in this scope” просто убрав using namespace std.

Java + Ant + сетевой диск

Java – наверное самая уродская платформа из всех, с какими я имел дело. Ну и Ant не дальше ушел.
Итак, дано: Linux, сетевой диск с парой гагабай исходников, ant, java, gcc. Простейшая команда ant clean приводит к исключению java.lang.OutOfMemoryError. Перепробовал все найденные в интернете способы изменения объема используемой памяти и прочих шаманских действий – не помогает.
Стал эксперементировать дальше, выяснил, что падает только на сетевых шарах(!!!). Скопировал локально – полет нормальный. Спрашиватся, ну какого хера ошибка OutOfMemoryError, а не что-то подходящее в данной ситуации?!
Вобщем, осталось только процесс копирования автоматизировать.

fstab

Это прям какая-то магия, но каждый раз когда я сталкиваюсь с fstab, у меня уходит куча времени на то чтобы в него что-то прописать. На этот раз мне понадобилось добавить Windows-шары на машину с Fedora 15. И теперь я решил все записать, чтоб уж в следующий раз точно не забыть как же это делается. Continue reading