А 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. Пацан сказал – пацан сделал.

stringstream сливает :(

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

Инициализация статического объекта в 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

C++ man(3)

Давно хотел разжиться маном по плюсам ибо задрало лазить в инет за этой информацией.
Подходящий ман берется вот тут: ftp://ftp.gwdg.de//pub/misc/gcc/libstdc++/doxygen/
И копируется вот сюда: /usr/share/man/man3
Ну а если к Vim-у добавить вот этот плагин, жизнь становится еще прекраснее :)))

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, единственное что остается – повторить запрос, предварительно указав параметры авторизации на проксе.

LLVM, чтоб его.

Баг 2008 года в LLVM портит мне жизнь. Берем тестовый файлик следующего содержания:

class RPC_Service
{
public:
  virtual ~RPC_Service ();
};
class EventLoggingInterface
{
  virtual void
    Ev (const char *file, int line, int sev, const char *fmt,
        ...) const = 0;
};
class RPCCore : RPC_Service, EventLoggingInterface
{
  virtual void
    Ev (const char *file, int line, int sev, const char *fmt, ...) const;
};
void
RPCCore::Ev (const char *file, int line, int sev, const char *format, ...) const
{
}

Выполняем команду:

/Developer/usr/bin/llvm-g++ thunk_error.cpp -c

И в результате получаем:

thunk_error.cpp:19: error: generic thunk code fails for method ‘virtual void RPCCore::Ev(const char*, int, int, const char*, ...) const’ which uses ‘...’

Неужели придется отказаться от LLVM? Интерфейс, в моем случае, поменять врятли удастся. Вобщем писать кроссплатформенный код это еще та засада

Работаем с таймерами.

До появления вот этой темы на РСДНе я как-то не предавал особого значения таймерам в Mac OS X. Ну есть они и есть, как будет нужно так разберусь. Но как оказалось, стандартных POSIX вызовов, таких как timer_create/timer_delete у нас нет, а то что есть не всегда подходит.

Хорошенько поковырявшись в документации я пришел к следующему выводу. Всего доступны 3 способа работы с таймерами, дающие приблизительно одинаковый эффект:

  • NSTimer из Foundation;
  • RunLoop из CoreFoundation;
  • Таймеры из Mach. Хотя у меня данный пункт вызвал некоторые трудности.

Так что по порядку, с краткими иллюстрациями.

Continue reading