суббота, 21 июля 2012 г.

Подключение к VirtualBox физического жесткого диска

Вы можете создать виртуальную машину, работающую со специальным *.vmdk-диском, в действительности напрямую отображаемом в реальный жесткий диск, в том числе внешний.

Так создается описанная связь (предполагается, что вы хотите создать *.vmdk-диск с именем usb-hdd320 и соединить его с пустым физическим диском /dev/sdc, и все происходит в ОС семейства Linux):

# cd ~/VirtualBox\ VMs
# sudo vboxmanage internalcommands createrawvmdk -filename usb-hdd320.vmdk -rawdisk /dev/sdc

Вы должны получить сообщение "RAW host disk access VMDK file usb-hdd320.vmdk created successfully", если все прошло хорошо. Далее необходимо создать виртуальную машину с именем, например, minilab, для работы с жестким диском через *.vmdk файл:

# sudo vboxmanage createvm --name minilab --ostype Ubuntu --register
# sudo vboxmanage modifyvm minilab --memory 512
# sudo vboxmanage storagectl minilab --name "IDE Controller" --add ide
# sudo vboxmanage storageattach minilab --storagectl "IDE Controller"--port=0 --device=0 --type hdd --medium ~/VirtualBox\ VMs/usb-hdd320.vmdk

Если вы хотите подкючить к ней iso-образ инсталляционного диска с именем, скажем, installation_cd.iso, то по образу и подобию подключения жесткого диска можете сделать следующее:

# sudo vboxmanage storageattach minilab --storagectl "IDE Controller" --port=0 --device=1 --type dvddrive --medium ~/VirtualBox\ VMs/installation_cd.iso

Запускается виртуальная машина minilab так:

# sudo vboxmanage startvm minilab

Можно провести сколь угодно сложную работу жеским диском в виртуальной машине, затем подключить его физически и загрузиться.

понедельник, 30 апреля 2012 г.

Objective-C

Если вы давно хотели попробовать, что же такое Objective-C, но не знали, с чего начать, то вам определенно будет более, чем достаточно на первое время материала двух лишь только статей:
википедии и руководства по GNUstep

UPD.
Ну и разумеется замечательная страничка документации по GNUstep.

среда, 11 апреля 2012 г.

Qt & multiple definition

QГрабля#5


При инстанцировании шаблонов внутри классов, использующих мета-объектную систему Qt, а также в ряде других ситуаций при использовании этой библиотеки (на практике особенно часто - при создании Unit-тестов силами QTestLib) возможно возникновение ошибки линковки multiple definition. Связано это с тем, что moc парсит заголовочные файлы и для всех файлов, содержащих класс с макросом Q_OBJECT генерирует *.cpp-файл с необходимым для функционирования мета-объектной системы Qt кодом. Такой файл становится отдельной единицей компиляции, и если в нем, как пример, инстанцируется какой-либо шаблон, то он, согласно правилам компиляции шаблонов C++, полностью включается в генерируемый объектный файл. Врочем, ровно то же происходит при инстанцировании такого шаблона в любом другом *.cpp файле, например, содержащем main(). В итоге в ходе линковки один и тот же шаблон обнаруживается сразу в нескольких объектных файлах, что и приводит к возникновению описанной выше ошибки.

Поправить ситуацию можно несколькими способами. Можно все методы шаблона сделать
inline-овыми (см. описание похожей ситуации), можно модифицировать сборку Qt-проекта вручную так, чтобы генерируемый moc'ом файл просто включался в файл, по которому он был сгенерирован (именно это в простых случаях автоматизировано выполняет этот скрипт (см. замечания)) Либо можно позволить линковщику самостоятельно разрешать такие конфликты, просто выбирая первое из многочисленных определений (ключ -z muldefs для *nix-линковщика ld) Интегрировать нужные ключи можно автоматически в Makefile с помощью этого скрипта (см. описание), либо просто ключив в *.pro-файл строку вида:

QMAKE_LFLAGS += -z muldefs


понедельник, 12 марта 2012 г.

Перенесу сюда сообщение из своего аккаунта в контакте:
Выяснение отношений с непокорным C++ привело меня к заключению, что чтобы детально разбираться во всех тонкостях инициализации и уничтожения объектов классов нужно положить на это жизнь. Если при попытке писать что-то ООП-шное вы часто получаете непонятные ошибки, возможно, причина кроется как раз в непонимании одного из 847528345-и моментов, касающихся именно этой области C++. Очень хорошо эти вопросы освещены в соответсвующих главах Брюса Эккеля "Философия C++, том 1", в которых будет проще и продуктивнее следить за мыслью автора с помощью вот этого: https://github.com/ramntry/constructors
Получить пакет и попробовать запустить пример на *nix-совместимых системах можно следующим образом:

git clone git://github.com/ramntry/constructors.git
cd constructors
./constructors -f examples/virtual_destructors.cpp
В системе должны быть установлены bash (или другой совместимый shell), git, g++ (gcc) и sed

понедельник, 5 марта 2012 г.

Qt и шаблоны

Не пытайтесь создать шаблонный класс, использующий мета-возможности Qt - в текующей реализации (Qt 4.8) ключевое слово template перед заголовком класса и макрос Q_OBJECT в его приватном блоке вещи несовместимые (просто шаблонный наследник QObject имет право на существование, но ведь это уже совсем другая история)

Поведение системы сборки Qt

QГрабля#4

Во многих случаях вам не удастся тривиальным образом скомпилировать код, который определяет класс, использующий расширенные возможности Qt, в том же файле, в котором расположена функция main - этот класс едва ли будет обработан утилитой MOC.

Решение

Всегда определяйте Qt-классы в отдельных заголовочных файлах. Реализация такого класса допустима как in situ, так в *.cpp-файле.

UPD


Также об этой проблеме можно почитать в небольшой ветке форума Qt

Управление памятью в Qt

QГрабля#3


Известно, что немалая часть объектов Qt, с которыми приходится иметь дело, в той или иной мере являются контейнерами для других объектов, иногда это непосредственно так (например, для layout'ов), иногда вырождается в повсеместно существующую возможность назначить объекту некоторого родителя. Так или иначе, крайне часто вы передаете в метод (в т. ч. конструктор) объекта указатель на другой объект. Не таким уж странным в таком случае кажется решение создать объект на стеке, а в случае необходимости его куда-то передать просто использовать оператор взятия адреса.

Однако Qt в рамках своей юрисдикции сама управляет памятью - если вы удаляете объект, его деструктор автоматически удаляет всех своих детей и (вероятно) элементы, содержащиеся в нем. Естесственно, ей невозможно знать, был ли создан указатель операцией new, или он указывает на объект, для которого вовсе не освобождалась память в куче - при удалении вашему указателю сделают delete, что выльется в реальной практике в backtrace и memory dump на экран при завершении Qt-шного приложения, если этот указатель увел delete на стек. Однако если вы все объекты будете создавать в куче не заботясь об их удалении, то вы получите утечки памяти. Ясно, что позаботиться обо всех объектах также невозможно разумным образом - в частности, не удалить экземпляр QApplication (QCoreApplication) без странных костылей типа

int returnCode = app->exec();
delete app;
return returnCode;

которых вы никогда не увидите ни в одном руководстве по Qt. Ровно те же проблемы возникнут с объектом главного окна приложения.

Решение.

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


UPD


Несомненно более точно и тонко проблему освещает таки документация Qt
QГрабля#2


Если ваш класс использует систему свойств Qt, то вы можете неожиданно получить проблему на стадии компиляции при попытке вызвать setProperty.
( <YourClass or ParentClass>::setProperty("PropertyName", propertyValue); )

Вам сообщат что-то в духе
"no known conversion for argument 2 from <propertyValueType> to ‘const QVariant&"

Проблема связана с тем, что по известным причинам свойства имеют тип QVariant, а в данном блоке кода компилятору просто не известен этот тип.

Решение

Включайте заголовочный файл <QVariant> (QtCore/QVariant> в файлы-определения классов,
использующих свойства Qt. (или даже в main-файл)

Этим сообщением я начну небольшую серию постов про грабли, с которыми, вероятно, столкнется каждый начинающий пользователь фреймворка Qt. Тривиальных вещей здесь не будет, они прекрасно изложены в первую очередь в документации самого Qt, которая вряд ли имеет равных себе по качеству, охвату и незанудности.

QГрабля#1


Если в приватной секции определения класса, использующего метаобъектную систему Qt, вы забыли указать макрос Q_OBJECT, а затем исправили свою оплошность, то вы вполне можете снова (и снова, и снова...) получить ошибку компиляции со словами в духе "undefined reference" и "vtable of <YourClass>" в строках клиентского кода, использующих в вашем классе дополнительные возможности наследников QObject (сигналы и слоты, свойства, возможности интроспекции).
Подобное может произойти в том случае, если ранее ваш класс, определенный без макроса Q_OBJECT уже успешно компилировался (то есть, дополнительные возможности не использовались) - и в папке сборки уже лежит Makefile, сгенерированный по *.pro-файлу утилитой qmake. Дело в том, что даже после внесенных исправлений, пересборка проекта заключается в вызове make, подхватывающей старый Makefile, который не вызывает MOC для файлов вашего класса (так что даже make clean не поможет).

Решение


Вручную удалите Makefile в директории сборки проекта и пересоберите его.

Так же полезно завести в директории ~/bin файлик с содержимым вроде


#!/bin/sh
if [ -e "Makefile" ]
then
    make clean
    rm Makefile
fi
qmake -project
qmake
make
(не забудьте сделать chmod +x <имя файла> и убедиться в том, что ~/bin есть в переменной окружения PATH (иначе можно ее туда добавить, дописав в ~/.profile строку
PATH="$HOME/bin:$PATH" ))

... и затем собирать проекты вызовом этого скрипта. У меня это выглядит так:

qqmake


воскресенье, 1 января 2012 г.

Мучает info?

Когда-нибудь Emacs придется освоить, ну а пока - перенаправляйте:

user@host cwd$ info something | less

Парсер параметров ядра

Код, стиль и подход которого почитателями всевозможных высокоуровневых style-guide'ов будет осужден и высмеян. Однако - что в этом фрагменте кода ядра непрозрачно, трудноподдерживаемо или опасно? Смотрите сами.

Linux-kernel в комментариях

Скотт Максвелл, первое издание на русском языке, неплохая интернет-версия