Про умные компиляторы

Есть категория людей, которые считают, что компиляторы очень умные. Что якобы можно писать любой код, а компилятор во всём разберется и соптимизирует как надо.

На самом деле компилятор это всего лишь программа. Как и любая другая программа, это просто последовательность действий, записанная человеком, которую выполняет компьютер. Кроме того существуют различные свойства программы, вроде pointer aliasing, которые вывести сложно, а иногда, если у вас нет всего-всего кода программы, то и не возможно.

http://locklessinc.com/articles/vectorize/ — я считаю замечательная статья, показывающая как легко компилятор может выдать неоптимальный код.

техподдержка

Интересные личности работают в техподдержке.

Как-то раз я репортил баг в micrоsоft cоnneсt об их компиляторе. Что-то вроде, что такой код у вас компилируется, а вообще не должен. Мне отвечают: "у нас не компилируется". Хм. Как так? Я же всё проверял.

А не могло ли так получится, что посланная программа не слинковалась из-за того, что я не написал функцию main? Я дописал пустую функцию main, и у них всё воспроизвелось. Т.е. обезьяна которая репродюсила баг даже не пыталась понять о чём он. Произошла ошибка на этапе компиляции или линковки — она ничего не понимает.

А вчера я купил Guitar Pro 6. И столкнулся с кучей проблем при его установке. Например, эти сказочные ребята шипают вместе с собой старую версию libz, а libxml2, который зависит от libz, нет. На новых системах libxml2 собран с использованием новой версии libz и естественно Guitar Pro на них не запускается. Это не единственная их проблема, там таких много.

Как хороший пользователь я решил написать им подробный отчет о том, какие у меня возникли проблемы при установке Guitar Pro 6. Написал. Получил ответ: "Guitar Pro не совместима с 64-битными версиями Linux".

Чуваки! Вы шипаете низкоуровневую библиотеку, а то, что он нее зависит — нет. Как это связано с битностью системы? Надо признаться, что одна из описанных мной проблем, действительно, была связана с 64 битной системой. Но остальное-то применимо к любой битности.

Мне кажется, что у них в техподдержке работают тупые обезьяны, которые увидели число 64, и послали шаблонный ответ "бла-бла-бла, 64 бита не поддерживается, бла-бла-бла".

Теперь сижу и думаю, стоит ли вступать с ними в переписку.

красота сообщений об ошибках MSVC

Ребята из clang хвалятся сообщениями об ошибках. Что ж, у MSVC тоже есть чем удивить пользователей.

void f()
{
    int * x;
    int * y;
    x - y;
}

main.cpp(5): warning C4552: '>>' : operator has no effect; expected operator with side-effect

#include <vector>

struct x
{
    operator int[]();
};

struct y
{
    operator long[]();
};

struct z
{
    operator wchar_t[]();
};

struct w
{
    operator std::vector<int>[]();
};

main.cpp(5): error C2092: '.H' array element type cannot be function
main.cpp(10): error C2092: '.J' array element type cannot be function
main.cpp(15): error C2092: '._W' array element type cannot be function
main.cpp(20): error C2092: '.?AV?$vector@HV?$allocator@H@std@@@std@@' array element type cannot be function

upd: Breaking News!

Микрософт ответили почему MSVC ругается на a - b сообщением про оператор >>. Внутри они заменяют a - b на ((size_t)a - (size_t)b) >> 2. Это означает, что если размер объектов куда указывает указатель не степень двойки, сообщение будет ругаться на деление! А если размер равен 1, то на вычитание! Проверил. Так и есть.
  • Current Music
    Sonata Arctica - Picturing The Past

пятиминутка любви MSVC

MSVC парсит некоторые виды тайпкастов за экспоненту:
int main()
{
    (int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())
    (int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())
    (int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())(int())0;
}

На этом коде компилятор некоторое время думает, а потом падает с out of memory.

Такой код вводит его в бесконечный цикл (в парсере):
__if_exists(TT)
{

А такой код, содержащий не парные фигурные скобки, компилируется без ошибок:
struct TT {};

__if_exists(TT)
{

Такое (некорректное) объявление шаблона класса приводит к крашу:

template <typename A, typename A1>
struct X
{
    template <typename B>
    struct Y
    {
        template <typename C>
        struct Z;
    };
};

template <typename A, typename A1>
template <typename B>
template <typename C>
struct X<A1, A>::Y<B>::Z
{
};

Но если бы классов X, Y, Z было бы только два, то краша бы не было.

MSVC режектит такой код
#define M void g() { int a = __LINE__; }

void f()
{
    struct x
    {
        M
    };
}

с сообщением об ошибке
main.cpp(7): error C2065: '__LINE__Var' : undeclared identifier

Но если выключить 'Edit and Continue' или если вытащить класс x из функции f или если сделать так, чтобы __LINE__ приходил не из макроподстановки ошибка исчезнет.

MSVC аксептит такой (неправильный) код:
struct a
{
    int x;
};

struct b : a
{};

struct c : a
{
};

struct x : b, c
{
    void g()
    {
        a::x = 5;
    }
};

throw expression

Не все знают, что в C++, throw это не statement, а expression. Поэтому такой код абсолютно корректен:

#include <stdexcept>

struct x
{
    x(int a)
        : a(a > 0 ? a : throw std::runtime_error("a is out of range"))
    {}

private:
    int a;
};

Какой тип имеет throw expression? По дефолту throw expression имеет тип void. Но если throw expression это второй или третий аргумент тернарного оператора то, тип тернарного оператора определяется другим его аргументом.
  • Current Music
    Luca Turilli's Rhapsody - Ascending to Infinity

Новое поколение текстовых файлов

Файл состоит из одной секции, содержащей одну пару ключ-значение:
[General]
torrents="@Variant(\0\0\0\x1c\0\0\0\x15\0\0\0P\0\x37\0\x62\0\x37\0\x38\0\x30\0\x61
\0\x30\0\x35\0\x39\0\x66\0\x30\0\x38\0\x30\0\x64\0\x65\0\x30\0\x64\0\x64
\0\x31\0\x32\0\x65\0\x35\0\x33\0\x63\0\x61\0\x34

...и ещё много страниц заэкранированного текста.

Видимо, ребята которые писали qBittorrent, слышали, что текстовые файлы, чем-то лучше бинарных, но вот забыли, чем именно.

P.S. Перед тем посылать пост, мне стало интересно, что за UTF-16 строчка закодирована в тесте. Это Info Hash. Да-да, это Info Hash записаный как UTF-16 строчка, сериализованная вот в такой текст. Facepalm.
  • Current Music
    Luca Turilli's Rhapsody - Of Michael The Archangel And Lucifer's Fall

Наблюдение

Одно наблюдение.

Возмем какую-нибудь толстую книжку. Например, Кормена (1300 страниц). С одной стороны это достаточно узкоспециализированная книжка. Ну действительно, она рассказывает про Computer Science, который является достаточно специализированным разделом математики. Который, кстати, ещё и достаточно молодой. Он появился, ну, грубо говоря, 60 лет назад. До этого это просто не было никому интересно. (не будем вспоминать диофантовы уравнения и перечислимые множества)

С другой стороны, Кормен очень обзорная книжка. Например, в нем есть глава "Вычислительная геометрия" на 40 страниц (самое-самое простое).

По вычислительной геометрии есть книжки на 1500 страниц (Handbook of Discrete and Computational Geometry). При этом там глава "Robust geometric computation" — ну в ней нет почти ничего. И по этой теме сейчас пишется отдельная толстая книжка.

Вопрос. Предположим, мы бы писали книжку "Математика" с достаточно детальным уровнем изложения. Сколько страниц была бы эта книжка?
  • Current Music
    Halford - Made in Hell