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

Перенесу мой пост на хабре.

RAII и необрабатываемые исключения 

Наверняка все знают прописную (в книгах про С++) истину о чудесной методологии RAII, если нет — приведу краткое описание из википедии.

Это шаблонное описание этой техники
Получение ресурса есть инициализация (англ. Resource Acquisition Is Initialization (RAII)) — программная идиома объектно-ориентированного программирования, смысл которой заключается в том, что с помощью тех или иных программных механизмов получение некоторого ресурса неразрывно совмещается с инициализацией, а освобождение — с уничтожением объекта.

Типичным (хотя и не единственным) способом реализации является организация получения доступа к ресурсу в конструкторе, а освобождения — в деструкторе соответствующего класса. Поскольку деструктор автоматической переменной вызывается при выходе её из области видимости, то ресурс гарантированно освобождается при уничтожении переменной. Это справедливо и в ситуациях, в которых возникают исключения. Это делает RAII ключевой концепцией для написания безопасного при исключениях кода в языках программирования, где конструкторы и деструкторы автоматических объектов вызываются автоматически, прежде всего — в C++.

Последнее предложение вроде как обещает 100% гарантию результата, но как всегда в жизни, а особенно в С++, есть ньюанс. 

Пример кода использующего RAII:

Допустим, есть какой-то класс, инкапсулирующий доступ к сети:

class Network{
public:
    Network(const URL &url) : m_url(url)
    {
    }

private:
    Url m_url;

};

Создаём класс, который будет реализовывать RAII:

class LockNet{
public:
    LockNet(const Url &url){
        m_net = new Network(url);
    }
    ~LockNet (){
        delete m_net;
    }

    operator Network * (){
        return network;
    }

private:

    Network *m_net;
};

Теперь в функции main мы можем безопасно использовать этот ресурс:

int main(int argc, char *argv[])
{
    LockNet net("http://habrahabr.ru")
    //здесь какие-то другие функции, 
    //которые могут генерировать исключения
    return 0; 
}

Вроде бы всё нормально, как обещает RAII, даже если будет сгенерировано исключение, указатель m_net в классе LockNet будет корректно удалён. Правильно?

Увы, нет.

Почему-то в описании RAII обычно забывают написать, что для работы этой техники исключение ОБЯЗАНО быть перехвачено обработчиком исключений этого типа, иначе, если обработчик не будет найден, будет вызвана std::terminate(), которая аварийно завершит выполнение программы. Страуструп описывает это в книге «Язык программирования С++ (03)», глава 14.7.

Удаление локальных объектов зависит от реализации, где-то они будут удалены, где-то наоборот, чтобы разработчик мог увидеть состояние локальных объектов на момент исключения, в дебагере когда загрузит coredump. И рекомендует если вам нужно гарантированное удаление локальных объектов оборачивать код в функции main блоком try — catch (...), который перехватывает любые исключения.

Т.ч. в коде функции main, если будет исключение до оператора return 0;, мы получаем обычную утечку ресурсов.
Она не фатальная, так как ОС сохранит coredump и освободит ресурсы, занятые программой.

Как в этом убедиться? Пишем проверочный код!

В данном коде мы используем умные указатели, которые реализовывают технику RAII:

#include 
#include 
#include 
#include 
#include 

using namespace std;

class MyExc
{

};

class Slot
{
public:
    Slot(const std::string &str = "NONAME") : m_name(str)
    {
        cout << "Constructor of slot: " << m_name << endl;
    }

    virtual ~Slot()
    {
        cout << "Destructor of slot: " << m_name << endl;
    }

    void sayName()
    {
        cout << "Slot name is: " << m_name << endl;
       throw MyExc();
    }

private:
    string m_name;
};


void testShared(shared_ptr & m_share)
{
    m_share->sayName();
   
}

int main()
{
    vector<shared_ptr> vec {make_shared("0"), make_shared("1"), make_shared("2"), make_shared("3"), make_shared("4")};

    for (auto& x:vec)
            testShared(x);



    return 0;
}

Скомпилировав и запустив эту программу, получаем вывод:

Constructor of slot: 0
terminate called after throwing an instance of 'MyExc'
Constructor of slot: 1
Constructor of slot: 2
Constructor of slot: 3
Constructor of slot: 4
Slot name is: 0

Переписываем функцию main, заворачивая вызов функции генерирующей исключение в try — catch блок:

int main()
{
    try {
        vector> vec{
            make_shared("0"),
            make_shared("1"),
            make_shared("2"),
            make_shared("3"),
            make_shared("4")
        };

        for (auto &x:vec)
            testShared(x);

    } catch (std::exception & ex){

        cout<
    } catch (...){

        cout<<"Unexpected exception"<    }
}
  


И, вуаля — всё начинает работать как и должно. 

Вызываются не только конструкторы, но и деструкторы объектов, хранящихся в умных указателях.

Вывод программы:

Constructor of slot: 0
Constructor of slot: 1
Constructor of slot: 2
Constructor of slot: 3
Constructor of slot: 4
Slot name is: 0
Unexpected exception
Destructor of slot: 0
Destructor of slot: 1
Destructor of slot: 2
Destructor of slot: 3
Destructor of slot: 4


Тем не менее, всё согласно стандарту:

15.2 Constructors and destructors

1. As control passes from a throw-expression to a handler, destructors are invoked for all automatic objects
constructed since the try block was entered. The automatic objects are destroyed in the reverse order of the
completion of their construction.

3. The process of calling destructors for automatic objects constructed on the path from a try block to a
throw-expression is called “stack unwinding.” If a destructor called during stack unwinding exits with an
exception, std::terminate is called (15.5.1).

15.3 Handling an exception

9 If no matching handler is found, the function std::terminate() is called; whether or not the stack is
unwound before this call to std::terminate() is implementation-defined (15.5.1).


Проверялось на g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2, Visual Studio 2013 CE.

Ссылки


RAII
ISO C++

вторник, 1 ноября 2011 г.

Ubuntu 11.10 vs Intel 5150 wifi

Установил Ububntu 11.10 на нетбук Acer Aspire One 531. После установки не заработала эта wifi карта.
NetworkManager в своём меню выводил: "управление беспроводными адаптерами отключено".

После добавления строки
blacklist acer-wmi в файл /etc/modprobe.d/blacklist.conf

и последующей перезагрузки wifi чудесным образом оживает.

суббота, 20 ноября 2010 г.

Build Gtkmm application in Eclipse CDT

После того, как вы установили пакет gtkmm-x.x-dev соответствующей версии, может возникнуть желание использовать удобный инструмент для разработки, к примеру весьма популярный Eclipse  с плагином CDT - для разработки С++ программ.
итак создаём стандартный ппроект С++, и пигем тестовую заготовку, но сразу видим, что Eclipse не видит заголовочных файлов библиотеки.
Main window

















Добавляем каталог с заголовочными файлами в свойствах проекта, для нужной конфигурации (Debug\Release).

Include settings


















Однако попытка собрать проект, успехом не увенчалась, так как нужно сообщить компилятору и линковщику о нахождении библиотек и всех заголовочных  файлов gtkmm
Build error

сообщяем компилятору, будьте внимательны с указанием правильной версии, которую вы установили или хотите использовать, в строке:
`pkg-config gtkmm-2.4 --cflags --libs`

compiler settings

сообщяем линковщику, будьте внимательны с указанием правильной версии, которую вы установили или хотите использовать, в строке:
`pkg-config gtkmm-2.4 --cflags --libs`
Linker settings

















Компилируем


Compiling













Запускаем

Runing

воскресенье, 12 сентября 2010 г.

Mac OS X in VirtualBox

Запустил Retail OS X в VirtualBox по этому рецепту


  1. Запускаем virtualbox и создаем виртуальную машину с именем «MacOS», указываем в качестве гостевой операционной системы Mac OS X Server, остальное по умолчанию.
  2. Открываем настройки созданной виртуальной машины. В настройках приводов, если присутствует SATA, меняем его на IDE (ICH6). Там же для привода компакт-дисков устанавливаем галочку «passthrough» — без этого виртуальная машина под windows не сможет загрузится с установочного компакт диска MacOS X.
  3. Закрываем virtualbox, запускаем консоль, делаем cd в папку с virtualbox и выполняем следующую команду:
    VBoxManage setextradata "MacOS" "VBoxInternal2/SmcDeviceKey" "ourhardworkbythesewordsguardedpleasedontsteal(с)AppleComputerInc"
    Где «MacOS» — имя созданной виртуальной машины.  .
  4. Запускаем virtualbox, стартуем виртуальную машину, в появившемся окне визарда выбираем что cd-приводом будет физический привод, вставляем в него установочный диск с MacOS X и, если все сделано правильно, то virtualbox грузится с диска и начинается установка. Если же вместо этого показывается желто-черное EFI Menu — то с диска загрузиться не получилось. Либо процессор не тот, либо не сделано что-то из вышеописанного.

воскресенье, 16 мая 2010 г.

Skype && Ubuntu 10.10 x86-64

Переустанавливал пакеты, и случаем удалились ia32-libs, как не имеющие зависимости, после чего skype, установленный в версии с динамической линковкой, скачанный с сайта Skype.com, перестал запускаться. Просто не запускаясь и ничего не выводя в консоль.
После установки этого пакета (ia32-libs) всё заработало нормально.

четверг, 25 марта 2010 г.

Git config

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

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

git config --global user.name "My name"
git config --global user.email "my@email.com"

Помимо этого я  прошу git отобрать состояния репозитория разными цветами, следующими  коммандами:

git config --global color.branch "auto"
git config --global color.status "auto"
git config --global color.diff "auto"

После чего изменения и новые файлы будут выделены цветом.
Примерно вот так:

воскресенье, 21 февраля 2010 г.

CNTLM - NTLM proxy для Linux

После установки NTLMAPS (написана на питоне) решил поискать аналоги из мира бинарного кода. Коллеги напомнили про программу зовущуюся CNTLM. (plain C)
Авторы программи приводят доводы о том, что программа более быстрая чем NTLMAPS и намного более производительная...
Останавливаем NTLMAPS
$sudo service ntlmaps stop
Удаляем NTLMAPS
$sudo aptitude remove ntlmaps
Устанавливаем конкурента
$sudo aptitude install сntlm
Настройка производится в конфигурационном файле
$sudo kate /etc/cntlm.conf
В котором указываем:
Имя пользователя
Домен
Пароль
Порт, который слушает программа

Примерно вот так:


После чего перезапускаем сервис
$sudo service cntlm restart

Пользуемся...
правда через неё Akregator не работает... Ох придётся взять как-нибудь сорцы в руки и диалог настройки прокси добавить...
Зато работает SVN, который через ntlmaps не работает.

NTLMAPS - NTLM proxy для Linux

Мне никак не удавалось настроить Akregator на работу через прокси сервер с NTLM аутентификацией, хотя Konqueror работал.
Помимо этого регулярно отваливались плазмоиды которые обращаются к серверам интернета для получения данных (microblogging, weather) - спустя какое-то время показывался диалог аутентификации и хотя пароль там был правильный, простое нажатие на кнопку "ОК" - сообщало, что произошла ошибка аутентификации, но если набрать пароль заново и нажать "ОК", тогда всё продолжало работать...
после нескольких нажатий "ОК" без перенабирания пароля- аккаунт блокировался на некоторое время...
Естественно назвать это нормальной и удобной работой никак нельзя...
И вот сегодня случайно наткнулся на описание этой программы...
Ставим на примере Kubuntu
$sudo aptitude install ntlmaps
После установки будет показан диалог конфигурирования, который можно вызвать в любой момент командой:
$sudo dpkg-reconfigure ntlmaps

Картинки по шагам:

Порт
Port  for local proxy

Корпоративный прокси



Порт корпоративного прокси



Домен


Логин пользователя в домене Windows



Пароль пользователя Windows



После этого прокси севрвер запускается и добавляются записи в стартап скрипты.
Теперь перенастраиваем систему для использования локального прокси сервера, после чего всё будет работать как надо!

Переменные окружения



КДЕ



APT



Итог:


При указании адреса прокси в настройках системы или программах - НЕ ЗАБЫВАЙТЕ УКАЗЫВАТЬ ПРЕФИКС http:// - иначе работать не будет.

понедельник, 9 ноября 2009 г.

Aptitude through proxy (Kubuntu 9.10)

У нас используется прокси с авторизацией.
Чтобы Aptitude(apt-get) мог работать через прокси, необходимо в файле /etc/apt/apt.conf прописать такую строку:
Acquire::http::Proxy "http://логин.пользователя:пароль@IP_прокси_сервера:порт"; <- не забыть поставитьв конце строки ";"
и перевести строку (нажать Enter).

Для удобства также в файде .profile прописываем переменные окружения (уже без знака ";")

export HTTP_PROXY="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export FTP_PROXY="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export RSYNC_PROXY="http://логин.пользователя:пароль@IP_прокси_сервера:порт"


Это нужно, чтобы разные программы могли работать через прокси, через предварительно установленные переменные окружения.
(особенно консольные - wget, git...)
Да и настройки прокси к примеру в KDE я ставлю, эти переменные окружения - чтобыб поменяв их в файле .profile не нужно было менять в остальных ппрограммах (правда firefox - их почему то не видит)

Сегодня обратил внимание, что flash плеер не ставиться по той причине, что он скачивается через wget пакетом flash-installer, и как выяснилось wgetу нужно переменную прокси прписать в нижнем регистре, что и было сделано:

export HTTP_PROXY="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export http_proxy="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export FTP_PROXY="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export ftp_proxy="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export RSYNC_PROXY="http://логин.пользователя:пароль@IP_прокси_сервера:порт"
export rsync_proxy="http://логин.пользователя:пароль@IP_прокси_сервера:порт"


Теперь всё работает нормально.

воскресенье, 1 ноября 2009 г.

Kubuntu 9.10 & alc260

Поставил свежевышедшую Kubuntu 9.10 на HP DC 7600.
Переделанный инсталятор радует глаз.


Поставил шрифты Droid. Рендерятся они намного лучше чем в 9.04. Работать очень приятно.
Немного подпортило впечатление звук на кодеке alc260. Гулкий, как будто в ведро говорят и ВЧ нет.
Надо просто выставить уровень звука немного разный для каналов и всё работает нормально.

суббота, 24 октября 2009 г.

QTableView прокрутка строк

Понадобилось по нажатию на кнопке формы прокручивать таблицу. Т.е. заменить scrollbar.
По нажатию кнопки сверху, поднимаемся на одну строку.
По нажатию кнопки снизу, опускаемся.
У QTableView таких методов нет. Зато есть методы scrollToBottom () и scrollToTop (), наследуемые от QAbstractItemView.
Также есть метод scrollTo ( const QModelIndex &, ScrollHint ), но у QModelIndex нет переопределённых операторов ++ и --.
Идём в исходники QAbstractItemView, который наследуется QTableView и видим:

void QAbstractItemView::scrollToTop()
{
verticalScrollBar()->setValue(verticalScrollBar()->minimum());
}

Значит делаем так:
void MyClass::scrollDown()
{
int current = tvPreview->verticalScrollBar()->value();
tvPreview->verticalScrollBar()->setValue(++current);

}


void MyClass::scrollUp()
{
int current = tvPreview->verticalScrollBar()->value();
tvPreview->verticalScrollBar()->setValue(--current);
}

среда, 7 октября 2009 г.

Восстанавливаем GRUB

Если вы затёрли mbr после, скажем, установки Windows и под рукой есть LiveCD ubuntu\kubuntu, нужно выполнить следующие шаги:

1. Boot from a Live CD, like Ubuntu Live, Knoppix, Mepis, or similar. Ideally use Ubuntu 8.04 or higher as this has NTFS write support and makes life a bit easier; this isn't necessary, just handy.

2. Open a Terminal. Open a root terminal (that is, type "su" in a non-Ubuntu distro, or "sudo -i" in Ubuntu). Enter root passwords as necessary.

3. Type "grub" which makes a GRUB prompt appear.

4. Type "find /boot/grub/stage1". You'll get a response like "(hd0)" or in my case "(hd0,3)". Use whatever your computer spits out for the following lines. Note that you should have mounted the partition which has your Linux system before typing this command. (e.g. In Knoppix Live CD partitions are shown on the desktop but they're not mounted until you double-click on them or mount them manually)

5. Type "root (hd0,3)" note the space between root and (hd0,3).

6. Type "setup (hd0,3)". This is key. Other instructions say to use "(hd0)", and that's fine if you want to write GRUB to the MBR. If you want to write it to your linux root partition, then you want the number after the comma, such as "(hd0,3)".

7. Type "quit".

8. At this stage you can either restart the system and install your own bootloader, or you can continue and tell the Windows bootloader where to find GRUB which will handle booting Linux.

пятница, 25 сентября 2009 г.

Windows 7 && Intel 945

Пробовал ставить Win7 на HP DC7100SFF с i915.
Aero не работал, более того, как выяснилось, Intel не собиралась выпускать для этого адаптера драйверы для Win7.
На днях поставил Win7 на HP DC7600SFF с i945.
Aero работает. Ничего не тормозит. Видимо M$ очень сильно постаралась над оптимизацией.

суббота, 19 сентября 2009 г.

Linux и шрифты.

Неумирающая вечная тема, красивых шрифтов в Linux.
Ставить шрифты Windows вроде как не совсем правильно по политическим причинам, а имеющиеся шрифты в Linux не вызывали удовлетворения, да и через некоторое время работы, уставали глаза. Явно было отставание от Windows.
Чего только не пробовал в разных комбинациях, ничего не устраивало...
то буквы размытые, то страшные...
Поставил из Android 1.5 - Druid Fonts.
Пока для меня это лучший вариант.


четверг, 9 июля 2009 г.

KDE 4 && Intel 915

Установив kubuntu 9.04 на довольно старый компьютер (HP DC 7100 SFF) с интегрированной видеокартой, никак не получалось использовать эффекты рабочего стола.
Тормозило всё просто невообразимо. Попробовал поставить Gnome с Compiz, но увы, Gnome тормозил ещё сильнее.
По наводке LestorN решил поиграться с методами ускорения в Хorg.
EXA - вроде как Интел убрала поддержку этого метода из своих драйверов начиная с XServer 1.6.
Что и было установлено опытным путём, добавление его в конфиг тормозов только добавляло.
UXA - новый метод. Добавление его в конфиг решило все проблемы с производительностью.
Отрывок из xorg.conf:

Section "Device"
Identifier "Configured Video Device"
Option "AccelMethod" "uxa"
EndSection

среда, 10 июня 2009 г.

Qt and Git part II

Итак все исходники после более длительной задержки, чем было обещано вначале, лежат тут.
Открываем любой нужный проект и смотрим подсказку (иконка хелпа)

The official Qt source code repository.

* Public clone url: git://gitorious.org/qt/qt.git

Если вы работаете за прокси-сервером, исходники можно тянуть через HTTP протоколу.
Нажмите иконку с ключиком и увидите ссылку на HTTP линк.

# HTTP clone url: http://git.gitorious.org/qt/qt.git More info…
You can clone this repository with the following command:
git clone http://git.gitorious.org/qt/qt.git
(note that cloning over HTTP is slightly slower, but useful if you're behind a firewall)

Чтобы гит тянул через проксю, необходимо в консоле указать HTTP_PROXY (в Linux\Mac нижним регистром)
Пример:
Windows
set http_proxy="http://User.Name:User.Pass@ip_proxy:port_proxy"
а дальше git clone http://git.gitorious.org/qt/qt.git
Linux\Mac
export http_proxy="http://User.Name:User.Pass@ip_proxy:port_proxy"
а дальше git clone http://git.gitorious.org/qt/qt.git
В Linux и Mac можно прописать переменную окружения в .profile (в windows не пробовал)

воскресенье, 25 января 2009 г.

Qt and Git

Для того, чтобы иметь возможность всегда иметь последний снапшот Qt под Windows и не тянуть его полностью, а получать только изменения делаем следущее:
1. Ставим MsysGit native порт Git под Windows, которому для запуска не нужет Cygwin
2. Идём на сайт QtSoftware в раздел Git
Внимательно читаем что там написано:
To clone one of these trees, install git, and run:
git clone git://labs.trolltech.com/ + project path.
For convenience, the clone URL is available as the "git" link below, or on the status page of any repository.

Смотрим список проектов.
Например, нам нужно получить последний снапшот Qt 4.5. путь проекта которого qt/snapshot/4.5
Переходим, к примеру, в C:\Qt
и в консоли пишем
git clone git://labs.trolltech.com/qt/snapshot/4.5 snapshot
Далее терпеливо ждём пока вытащится полное дерево исходников.
После чего, переходим в каталог
C:\Qt\snapshot

и компилим как обычно. Имя snapshot дано для примера, можно указывать какое угодно.
Для того, чтобы принять последние изменения, закомиченные QtSoftware, переходим в
C:\Qt\snapshot

и делаем
git pull
Будут скачены, только изменённые файлы.
Информацию по Git можно подчерпнуть тут, где есть небольшая community book, либо онлайн, либо PDF вариант , так же доступны screencasts, есть даже специально про установку под Windows.

среда, 14 января 2009 г.

Qt under LGPL

Сегодня Nokia объявила о том, что следующая версия Qt - 4.5 будет доступна под лицензией LGPL 2.1. В последующем, обещают переход на v.3.
Большой шаг вперёд, это открытие ветки разработки.
Теперь разработчики могут добавлять сами нужную функциональность, а не ждать, пока это сделает Nokia.
Разумеется, мердж веток будет делать сама нокия, предварительно проверяя качество кода.
Об этом сказал Eirik Chambe-Eng.

воскресенье, 16 декабря 2007 г.

Trolltech обновила интегратор для Eclipse до версии 1.0.1.
Эта версия собрана с Qt 4.3.3, выложена справка в формате Eclipse, для доступа к ней прямо из среды разработки.
Для программирования на Qt, замечательная связка.
Порядок установки такой:
1. Компилятор - скачиваем, устанавливаем.
2. Qt - скачивем, устанавливаем.
3. Eclipse - скачиваем, распаковываем.
4. Интегратор - скачиваем устанавливаем.
5. Запускаем, пользуемся.

Warning:
Так как сам Eclipse - Java приложение, для его работы должна быть установлена JRE от Sun
На Kubuntu надо провести следующие манипуляции для её установки:
sudo aptitude install java-package fakeroot
fakeroot make-jpkg jre-6u3-linux-i586.bin
sudo dpkg -i sunj2re.1.6_1.6.0+update3_i386.deb


И если вы используетет gtk-qt-engine, в центре управления выберите тему отличную, от текущей в кде.
Qtaxi - простая программа автоматизации такси, лицензия GPL.
Написано всё на Qt4\C++, как следствие работает на Linux, OS X, Windows.
Содержит 6093 строки чистого кода.
Qt 4.3.1 - минимум, настоятельно рекомендуются, в меньших версиях существуют проблемы с неправильным отображением дат в русской локали в QTableView.
Нашёл время дописать пользовательскую документацию к программе.
Для людей занимающихся программированием - это практически непосильный труд.
Выложены исходники с документацией и инсталятор под Windows.
Кто хочет сделать пакет для Linux, welcome.
Так как у самого нет опыта и мало свободного времени.
Скачать можно тут.