CMake & Clang

Решил изменить сборку с идущего по умолчанию GCC на Clang для CMake проекта. Сходу наткнулся на граблю. Стандартная команда CMake:

set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_C_COMPILER clang)

Вводит его в вечный цикл, который выглядит как-то так:

You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_C_COMPILER= /usr/bin/gcc
CMAKE_CXX_COMPILER= /usr/bin/c++

-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
…и так до бесконечности…

Лечится не удобно, но юзабельно:

export CXX=/usr/bin/clang++
export CC=/usr/bin/clang
cmake CMakeLists.txt
make

А GCC предупреждал…

Есть некий код, приблизительно следующего содержания (упрощенный вариант):

TRACE((ERROR, "Bla-bla-bla. Can't create struct (%terr)", err));

Причем, как мы выяснили с большим трудом, переменная err, это не некий интовый код ошибки, а млять C++ класс! (луч поноса автору этого говна). G++ это дело находит, и, пишет предупреждение:

warning: cannot pass objects of non-POD type ‘struct cERROR’ through ‘...’; call will abort at runtime

Но это предупреждение остается незамеченным среди остальных over 9000 предупрежденией. Но G++ не просто намекает, он еще и генениует вот такой код:

0x01d4fe77 :    mov    DWORD PTR [ebp-0x20],eax
0x01d4fe7a :    jmp    0x1d4fe7e <_ZN8KLParams11DeserializeERP13cSerializablej+668>
0x01d4fe7c :    ud2a  
0x01d4fe7e :    mov    eax,DWORD PTR [ebp-0x20]

Где “ud2a” is the guaranteed illegal opcode on ia32. Пацан сказал – пацан сделал.

Классическая задача для собеседования в реальной жизни

Случилось странное – я столкнулся с буквально классической задачей с собеседования в реальной жизни. Задача состоит в том, что необходимо найти первый не нулевой бит в массиве. Поиск должен происходить максимально быстро, скорость поиска желательно получить приближённую к линейной. Никаких правил по распределению единиц в массиве нет. Массив не велик и должен не вылезать за пределы одной кэш-линии.
Родились 3 варианта алгоритма, одна часть которого общая во всех случаях, вторая специфическая.
Общая часть сводится к поиску первого 32 разрядного слова с хотя бы одним не нулевым битом. Дальше, в найденном 32 разрядном слове ищем первый не нулевой бит. Я не знаю как можно оптимизировать первую часть алгоритма, так что ищу простым перебором. Continue reading

Коллекция Cocoa контролов

Я долгое время считал что количество дополнительных библиотек для Mac OS X и iOS очень скромное. В крайнем случае ни о каких библиотеках кроме как OmniGroup, BWToolkit и Sparkle я особо не слышал. Поэтому, сайт CocoaControls был для меня очень приятным открытием. Пусть большинство контролов и не подойдет для непосредственного использования, но вот как набор идей и подсказок сайт реально великолепен!

stringstream сливает :(

Не то чтобы я большой любитель C++, тем не менее всегда считал что форматирование через stringstream работает быстрее чем форматирование через sprintf. В очередной раз обсудив плюсы и минусы форматирования с коллегами, решили что проще “достать да померять”. Итог оказался довольно неожиданный для меня: stringstream позорно слил в лучшем случае в 2 раза, а в худшем в 3!
Continue reading

Работа с мэйкфайлами.

На просторах интернета нашел очень понравившуюся мне книгу посвященную работе с GNU Make – Managing Projects with GNU Make, 3.Xth Edition, которая еще и распространяется под GNU Free Documentation License. В книге подробно рассматривают работу с GNU Make начиная с азов и простейшего Makefile заканчивая вопросами производительности, отладкой Makefile и различными трюками.
Однозначно стоит прочесть!

Инициализация статического объекта в GCC

С удивлением узнал о том, что GCC гарантирует атомарность создания статического объекта. Поэтому следующий код будет корректен в многопоточном окружении:

template <typename T>
T& singleton()
{
    static T obj;
    return obj;
}

Если по каким-то причинам такое поведение кажется возмутительным, можно воспользоваться флагом -fno-threadsafe-statics

Кстати, кто знает как обстоят дела с инициализацией статических объектов у других компиляторов?

Легенда о константной ссылке.

Уже несколько раз в кругах C++ разработчиков слышал Легенду о константной ссылке. Легенда варьируется от “из функции можно вернуть константную ссылку на временный объект” до “можно сохранить константную ссылку на временный объект”. Как раз на прошлой неделе мы обсудили этот вопрос с коллегами, и мне захотелось в нем детально разобраться.
В стандарте данная ситуация освещена очень вскользь, так что пришлось покопаться. Во-первых, в пункте 12.2.5 сказано следующее:
Continue reading

Получаем стек вызовов в Mac OS X

Я давно хотел добавить поддержку получения стека вызовов к своему Tasks Explorer, но никакой публичной информации на этот счет мне не попадалось, а ковырять систему было некогда да и лень (зима, чтоб ее). С первыми лучиками весеннего солнца задача с получением стека вызов стала казаться не такой уж и скучной и дело сдвинулось.
Начал я с того, что нашел утилиту stackshot разработки Apple, только вот исходники приложения закрыты. Как вариант, stackshot можно было использовать напрямую, но в целом такая идея мне не понравилась, да и никаких новых и полезных знаний это не даст. Тем не менее, stackshot вполне сгодился в качестве отправной точки.
Continue reading

cURL & Proxy & HTTPS & Authorization == CURLE_RECV_ERROR

Да, баги в тулзах преследуют меня всю неделю. На сей раз отличился cURL с древним багом связанным с запросом отправляемым по HTTPS через прокси. Похоже что ситуация не слишком распространенная, т.к. надо не только работать через прокси, но еще на прокси должна быть включена авторизация и при отправке запроса пароль должен быть не указан. В принципе, в такой ситуации ожидаешь код 407, просишь пользователя ввести пароль и наступает счастье. Но вот cURL думает иначе. Вместо того чтоб вернуть 407 и страничку с ошибкой от прокси, которые судя по его логу присутствуют, зачем-то возвращается CURLE_RECV_ERROR.

Ignore 1380 bytes of response-body
Received HTTP code 407 from proxy after CONNECT
Closing connection #0
Failure when receiving data from the peer

Какого-либо корректного выхода из данной ситуации я не нашел. Так что, при работе через прокси, если пароль не задан и возникает ошибка CURLE_RECV_ERROR, единственное что остается – повторить запрос, предварительно указав параметры авторизации на проксе.