воскресенье, 16 сентября 2012 г.

Отладка C/C++ кода на Android

Отладка привычного, Java кода, не составляет проблемы – все работает из коробки. Но настала пара отладить код, написанный на C/C++. Что же делать?

суббота, 21 апреля 2012 г.

Java Reverse Engineering

Небольшая подборка утилит для “работы” с Java приложениями:

  • JD-GUI – отличный декомпилятор. Выдаёт вполне читаемый java-код. Есть удобная навигация по классам.
  • reJ – декомпилятор и редактор. Умеет декомпилировать в byte-код и редактировать его.
  • JBE – ещё один декомпилятор и редактор byte-кода.
  • jarw – самописная утилита, чтобы работать с jar-файлами под Windows, т.к. файловая система не различает регистр в именах файлов.
  • И на последок, редактор ресурсов ResEdit тоже может пригодиться.

Удачи!

воскресенье, 12 февраля 2012 г.

Сборка PyPy из исходников под Windows

На данную тему есть хорошее руководство “PyPy on Windows”, которое послужило для меня отправной точкой. Здесь я опишу некоторые дополнительные детали, которые могут вам пригодиться при сборке c использованием компилятора Microsoft Visual С++.

понедельник, 31 января 2011 г.

Private inheritance and std::auto_ptr

Some time ago I have encountered a problem. When I was writing implementation of an interface class, I forgot to specify inheritance access-specifier, so the private-inheritance is assumed by default. It is illustrated in the following example:

class A
{
public:
  virtual void Method() = 0;
  virtual ~A();
};

class B: /*private*/ A
{
public:
  virtual void Method();
};
 

And I used a factory to create an instance of the class B:

std::auto_ptr<A> CreateB()
{
  return std::auto_ptr<A>(new B());
}
 

As you must know, private inheritance limits access to a base class for B class clients.  But technically it is still accessible, see 11.2 paragraph 3 of the C++ standard:

Because of the rules on pointer conversions (4.10) and explicit casts (5.4), a conversion from a pointer to a derived class to a pointer to an inaccessible base class might be ill-formed if an implicit conversion is used, but well-formed if an explicit cast is used.

The previous code doesn’t use an explicit cast, but still compiles without any errors and warnings by Microsoft Visual Studio 2005 SP1 C++ compiler. It is known that this version has a bug in auto_ptr implementation, that allows any pointer to be passed in the constructor. But my header files was already patched (once I have spent several hours debugging a code). Then I wrote some more examples to test compiler behavior:

A* pa = new B();              // compile error, ok
B* pb = new B();

std::auto_ptr<A> a(new B());  // compile error, ok
a.reset(pb);                  // compile error, ok

std::auto_ptr<B> b(new B());
a = b;                        // compile error, ok

// oops! this works! o_O
return std::auto_ptr<A>(new B());
 

I’ve also tested this examples with the Microsoft Visual Studio 2008 and 2010.  Both still compiles without any errors and warnings, but the last displays IntelliSence error:

vs2010_hint

Fortunately I also compiled my code with GCC 4.4.3 compiler, and it works as it should be, producing an error: “A” is inaccessible base class of “B”. This is no a serious error, but this remind us that it is good when compiler finds out our typos, malformed and dangerous expressions. And it is good to set a maximum warning level when compiling code or use several compilers. As proverb says, two heads is better then one.

This is my first post in English, so feel free to send corrections. And of course, comments are welcome!

понедельник, 16 августа 2010 г.

Передавайте параметры по значению или по константной ссылке

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

int number = 0;
for (RecordVector::const_iterator it = records.begin();
  it != records.end(); ++it)
{
  SaveRecord(writer, *it, number);
}

Как Вы думаете, что здесь происходит интересного? В цикле сохраняются какие-то записи, при чем для каждой указывается некий номер number. Только вот незадача, number нигде не изменяется! Бессмыслица какая-то... автор не ведал что писал? И тогда начинает рождаться догадка. Надо посмотреть объявление функции SaveRecord. Это ключевой момент. Смотрим:

void SaveRecord(WriterPtr writer, const Record& value, int& number);

Ага! Предположения оправдались. Параметр number передается по ссылке и меняется где-то в недрах функции. Теперь все встало на свои места.
Вывод: передача параметра по ссылке усложнила понимание кода, пришлось смотреть объявление функции, следовательно, пришлось отвлечься и потратить время. А из-за большого количества параметров, длинных названий типов, namespace'ов, даже посмотрев сигнатуру функции, можно упустить ссылку из виду. Например, следующий код, легче для понимания:

int number = 0;
for (RecordVector::const_iterator it = records.begin();
  it != records.end(); ++it)
{
  SaveRecord(writer, *it, number);
  number = CalculateNextNumber(...);
}

Другие примером, является функция, которая кроме того, что возвращает значение, так еще и параметр изменяет. Ладно бы процедура (функция, которая возвращает void; кто писал на Pascal'е знает), но функция выносит мозг.

FruitPtr Gather(const Tree& source, FruitIdType& id);

Функция - есть функция, и должна возвращать один результат. Иначе стоит задуматься над ее разделением на несколько частей, каждая из которых будет возвращать единственный результат, или возвращать структуру.

Кстати, все примеры не что иное как частный случай нечистых функций. Передавайте параметр по ссылке только в исключительных случаях.
Передавайте параметры по значению или по константной ссылке. Удачи!

воскресенье, 4 июля 2010 г.

Qt widget для выбора цвета

Выкладываю простенький Qt widget для выбора цвета с дополнительной возможностью задать его строкой как в css. Этот widget я использовал в нескольких рабочих проектах, избавив меня от дублирования кода. Исходники (widget, designer plugin, example) можно взять здесь, а exe-шник здесь.

среда, 14 апреля 2010 г.

Материалы по C++ и ООП

C++
C++ Containers Cheatsheet
C++ Iterators and Algorithms
C++ Strings
Bit Twiddling Hacks
Bjarne Stroustrup's homepage
Finding a Loop in a Singly Linked List
C++ FAQ Lite

OOP
OOP Cheatsheet
Design Patterns Cheatsheet (1)
Design Patterns Cheatsheet (2)
UML Cheatsheet
Паттерны проектирования на русском

Вопросы на собеседовании
Заметки Белого Рыцаря - Задачи на собеседованиях
Interview Questions and Answers
The Nameless Blog

Книги
1) Stroustrup B. The C++ Programming Language - 3rd. ed.
2) Саттер Г., Александреску А. Стандарты программирования на С++. - Пер. с англ. - М.: Издательский дом "Вильямс", 2005. - 224 с.: ил. - Парал. тит. англ.
3) Саттер Г. Решение сложных задач на С++. Серия C++ In-Depth, т. 4.: Пер. с англ. - М.: Издательский дом "Вильямс", 2002. - 400 с.: ил. - Парал. тит. англ.
4) Саттер Г. Новые сложные задачи на C++. : Пер. с англ. — М.: Издательский дом "Вильямс", 2005. — 272 с.: ил. - Парал. тит. англ.
5) Дьюхерст С. С++. Священные знания. - Пер. с англ. - СПб.: Символ-Плюс, 2007. - 240 с.: ил.
6) Мейерс С. Эффективное использование STL. Библиотека программиста. - СПб.: Питер, 2002. - 224 с.: ил.
7) Джосьютис Н. C++ Стандартная библиотека. Для профессионалов - СП Питер, 2004. - 730 с.: ил.
8) Степанов А., Ли М. STL - стандартная библиотека шаблонов C++
9) Standard for Programming Language C++, Working Draft
10) Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приёмы объектно-ориентированного проектирования. Паттерны проектирования. - СПб.: Питер, 2001. - 368 с.: ил. (Серия "Библиотека программиста")
11) Бентли Дж. Жемчужины программирования. 2-е издание. — СПб.: Питер, 2002. — 272 с: ил.

понедельник, 15 февраля 2010 г.

Знакомство с Python

Пятничный вечер, 12 февраля. Засвидетельствованы первые упоминания о языке Python. Сейчас использую Python для неболших прикладных задачек, например, данные из одного формата в другой перегнать, файлики подправить. Несомненно надо его изучить, к тому же мне он понравился. Короче, Use The Source, Luke! Да, пребудет с тобой Сила.

пятница, 29 января 2010 г.

QTranslator, который поддерживает TS-файлы

И снова Qt! Эта запись касается перевода приложений, написанных на Qt, на другие языки.

Стандартная схема выглядит следующим образом. У нас есть текстовый файл перевода в xml-формате, и он имеет расширение ".ts". Затем этот файл компилируется в двоичный формат при помощи утилиты lrelease, и в результате получаем файлик с расширением ".qm". Готовые файлы переводов могут располагаться как отдельно от исполняемого файла приложения, так и включены в него как ресурсы. Преимущества такого подхода, высокая скорость работы и малый размер файлов перевода. Но есть и другой аспект. Как вы переводите своё приложение? Знаете много языков? Нанимаете переводчиков? Переводите переводчиком? (кстати как вариант чернового перевода, к тому же многие выражения состоят из пары слов. У меня была идея и частичная реализация через Google Translate :)). Но есть ещё один вариант - перевод конечным пользователем! Эта возможность позволяет перевести приложение на множество языков без особых усилий! Например, один из проектов, над которым я работаю, переведён уже на 27 языков. Поэтому файлы переводов распространяются в текстовом виде, а проще всего прямо в ts-формате. Для его чтения был написан небольшой класс TSTranslator. Для удаления "лишнего" из ts-файлов, например, номеров строк и имён исходных файлов, можно воспользоваться утилитой lconvert с параметром --no-ui-lines или --drop-tags. Я пользуюсь самописной утилиткой stripts. К сожалению, текущая реализация пока не поддерживает множественные формы числительных. Буду рад замечаниям и дополнениям.

tstranslator_src.zip

вторник, 12 января 2010 г.

Пара [не]нужных примочек для Total Commander

Тем, кто постоянно пользуется Total Commander может пригодиться.



1. Открытие командной консоли с административными правами в текущем каталоге


Открыть командную консоль просто: достаточно набрать в командной строке cmd или запустить её из меню. А вот открыть её с правами администратора проблемно. Постоянно приходилось делать это через "Пуск", при чём сначала надо открыть меню "Пуск", затем набрать cmd в строке поиска, дождаться пока она найдётся, открыть контекстное меню и только после всех этих действий запустить консоль с правами администратора. Но при этом консоль откроется в каталоге по-умолчанию "C:\Windows\System32". Это что?! Ещё и каталог надо ручками сменить! Конечно, можно создать ярлык к консоли с правами администратора и поместить его где-нибудь на рабочем столе или закрепить в том же меню "Пуск", но каталог то всё равно придётся менять в ручную. В конце концов мне всё это надоело и я решил эту проблему следующим образом. Нашёл в интернете утилиту (ссылка, файл), позволяющую запускать программы с правами администратора из командной строки, скинул elevate.exe в "C:\Windows\System32" и добавил кнопку на панель инструментов Total Commander. Команда - [elevate.exe], параметры [cmd /k "cd /d %P"]. И всё!





Добавлено 18.01.2010 12:36


Понадобилась мне такая фишка дома, но утилиты elevate.exe не оказалось, да и интернета не было. Буквально тут же в голову пришла новая идея. А почему бы не сделать всё это дело через обычный ярлык? Создаём ярлык на cmd.exe и в его свойствах указываем запуск с правами администратора. В качестве команды указываем полный путь к этому ярлыку (имеено к ярлыку), а параметры практически те же самые - [/k "cd /d %P"]



2. Открытие выбранных файлов в каталоге


Бывали случаи, когда приходилось редактировать несколько файлов одновременно в блокноте. Как это сделать? Я, например, запускал блокнот, выделял нужные файлы и перетаскивал их мышью в блокнот. Но хотелось бы выделить нужные файлы и одним нажатием клавиши открыть их все вместе для редактирования. Как я это сделал? Опять же через дополнительную кнопку на панели инструментов Total Commander. Но здесь есть препятствие с передачей списка выделенных файлов. Total Commander позволяет использовать специальный параметр %L для создания временного текстового файла со списком выделенных файлов. Поэтому пришлось создать небольшой cmd-файл для чтения этого файла и добавления имён выделенных файлов непосредственно в параметры командной строки вызываемого приложения. Этот cmd-файлик list.cmd я скинул в каталог с Total Commander, и он содержит следующее:


Copy Source | Copy HTML
@echo off
set LIST=
for /F "tokens=*" %%i in (%2) do set LIST=!LIST! "%%i"
start %1 %1 %LIST%



Соответственно, команда для кнопки будет [cmd /v /c list.cmd], параметры ["запускаемое_приложение" %L], а в качестве пути запуска нужно указать каталог, где лежит файл list.cmd.





Кстати в новой версии Total Commander 7.50 появился специальный параметр %S, который добавляет в командную строку имена выбранных файлов! С этим параметром всё значительно упрощается!