Category: it

Category was added automatically. Read all entries about "it".

Как пропатчить Remote Debugger 2012 под Windows XP

Вторая на данный момент по популярности винда более не поддерживается официально. Под нее не будут выпускаться патчи, ну почти. Но что действительно заставляет меня переходить с нее на что-то более новое, так это невозможность работы на ней Visual Studio старше 2010-й версии. Конечно, я не нахожу в этом серьезной проблемы, но по ряду причин XP у меня прочно засела на виртуалке, и я продолжаю ее использовать в таком виде. VC++ 2012/2013, кстати, хотя не работает на XP, но позволяет собирать под нее программы. В противном случае было бы очень сложно заставить разработчиков переходить на новые студии, потому что еще очень много стороннего софта заявляет поддержку старых винд. Но чтобы все-таки усложнить людям жизнь, под XP кроме самой студии не работает также Remote Debugger. То есть писать что-то под эту ненавистную MS операционку пока можно, но вот отлаживать уже никак (по крайней мере, в удобной среде VS). Это доставило мне некоторые неудобства, и я решил исправить ситуацию. Просто взял этот ремоут дебаггер и пропатчил, чтобы работал. Собственно, вот он. Правда, он умеет только native код, т.к. мне этого более чем достаточно. Если вам тоже, можно брать и юзать. Ну а для тех, кому просто интересно, суть проделанных извращений под катом.

Collapse )

Сокращение правого операнда побитового сдвига

Операторы побитового сдвига берут левый операнд и сдвигают его двоичное представление на количество бит (вправо >> или влево <<), указанных в правом операнде. В простейших случаях такие операции эквивалентны делению или умножению на степень двойки. Некоторые особенности появляются, если берутся числа отрицательные или знаковые. Например, в C++ (Глава Стандарта 5.8) сдвиг влево отрицательного значения ведет к undefined behavior, а сдвиг право определяется реализацией. Однако сдвиг положительного (или беззнакового) значения вправо E1 >> E2 всегда должен быть эквивалентен целой части E1 / 2E2.

Кстати, есть язык, в котором нет беззнаковых типов. В нем сдвиг вправо старшие биты заполняет не нулем, а значением знакового бита (для отрицательных чисел единицей). Поскольку это не всегда ожидаемое поведение, в языке есть специальный оператор беззнакового сдвига вправо >>>. Старшие биты он заполняет нулем.

Но это еще не все. В спецификациях языков C# (п. 14.8) и Java (п. 15.19) есть такое понятие, как сокращение правого операнда. В действительности сдвиг осуществляется не на то число бит, которое записано в правом операнде, а на его значение по модулю разрядности левого операнда. То есть происходит примерно следующее:
E1 >> (E2 % (sizeof(E1) * 8)) или, точнее,
E1 >> (E2 & (sizeof(E1) * 8 – 1))
Это приводит к неожиданным спецэффектам, например, сдвиг на 1000000 вообще не будет делать никаких сдвигов. Трогательную историю, зачем так было сделано, можно почитать здесь.

А вот совершенно внезапным для меня оказалось, что некоторые популярные компиляторы C++ тоже делают сокращение, хотя никакого намека на это я не нашел ни в Стандарте, ни в аннотированном руководстве. Я проверил в Visual C++ 2005, MinGW 4.5.2 и CodeGear C++ 2009 – во всех присутствует сокращение для всех целочисленных типов (кроме, разве что, long long, для которого оно есть лишь в MinGW).

Если кто-то знает причину этого странного явления, расскажите, а?

UPD: Visual C++ 2008/2010 и Intel C++ Compiler 11 выдают аналогичный результат.
Посмотрел, во что оно компилируется (VC++), получается что-то вроде:
mov esi, dword ptr [E1]
mov eсx, dword ptr [E2]
sar esi, cl
Здесь следует обратить внимание на семантику мнемоники sar. В качестве второго операнда может быть только конкретное значение, либо регистр cl (младший байт регистра ecx). В последнем случае происходит сокращение cl по маске 0x1F, то есть по модулю 32.

На код вида 121 >> 1000000; VC++ выдает предупреждение "shift count negative or too big, undefined behavior". Причины, почему too big приводят к ub, находятся за горизонтом моего непонимания, однако уже объясняют, почему все компиляторы ведут себя undefined.
  • Current Music
    Draconian — [Arcane Rain Fell #08] Death, Come Near Me

Ковариантные возвращаемые типы

Есть в C++ такая фича. Допустим, есть класс с виртуальным методом, возвращающим указатель на себя. Наследуясь от него, можно переопределить этот метод, причем в качестве возвращаемого типа допустимо использование указателя на производный класс. Этот механизм называется ковариантными возвращаемыми типами. Каноническим примером послужит метод clone, создающий копию объекта в куче и возвращающий указатель на него. Примерно так это может выглядеть:
 

Collapse )

  • Current Music
    ERA - [Era Classics #06] Malher + Adagieto + 5th Symphony

Совет труъ-программистам

Если вы считаете себя профессиональным программистом, пишете сложнейшие высокопроизводительные программные системы, которые распространяются на DVD, то в этом вам может помочь следующий код (секрет профессионалов!):
#define TrueCoder(Mb) class A{char a[Mb*1048576];public:A(){memset(a,-1,1);}};A a;

P.S. Компилировать в Release, VC++ 2005/2008.
  • Current Music
    Nightwish - [Century Child #08] Feel For You

Структуры данных .NET

Недавно в программе, реализуемой на C#, понадобился тип данных множество. Беглый поиск при помощи IntelliSense в пространстве имен System.Collections.Generic не дал положительных результатов. Священный источник знаний жрецов до-диеза оказался малоинформативным в данном вопросе. Впрочем, вскоре я обнаружил, что в .NET 2.0 такой простой и полезной структуры данных нет, а появится лишь в .NET 3.5. Казалось бы, мелочь, но странно то, что структуры данных носят намного более фундаментальный характер и имеют большую значимость (и необходимость), чем какая-нибудь сериализация или механизм reflection. Так или иначе, быдлокодеры разработчики дотнета не реализовали ни множество, ни удобный STL'ный класс pair, ни многого другого (разнообразных деревьев), касаемого структур данных.

Не забывайте, как с помощью веревки достаточной длины стрелять себе в ногу :)
  • Current Music
    Theatre of Tragedy - [Aegis #01] Cassandra