
Ковыряясь с багом в Konsole, попробовал “родную” IDE для программирования под KDE – KDevelop. Мне нужно было чтобы IDE умела:
- Импортировать проект из cmake-файла
- Редактировать C++ код с более или менее удобной навигацией
- Собирать проект, желательно одной кнопкой
- Запускать проект в отладчике, желательно одной кнопкой
Сначала думал попробовать Eclipse, так как нашел в сети инфу о каком-то плагине, который по cmake-файлу умеет генерировать eclipse project, но в jabber конфочке мне подсказали, что KDevelop умеет это делать из коробки.
В общем, с первым пунктом KDevelop вполне справился. Единственное замечание: импорт не работает, если вы выбираете папку с проектом, к которой у KDevelop нет доступа. Я скачал исходники из-под рута, а KDevelop был запущен под обычным пользователем. Проблема заключается в том, что KDevelop не сообщает о сути ошибки, а просто молча ничего не делает. Возможно, эта проблема уже исправлена в более свежих версиях (я работал с KDevelop в Debian, в который как известно, попадают не самые свежие версии пакетов). Работает также импорт из обычных make-файлов (которые появляются после выполнения ./configure). Так я сымпортировал туда же проект xterm (то есть для обычного make сначала нужно выполнить ./configure, а потом импортировать проект в KDevelop).
Второй пункт тоже отработал замечательно – навигация по С++ действительно хороша, IDE умеет переходить не только по Ctrl+Click к объявлению функции, но и по клику на сигнатуру объявления функции – к её определению. Также хорошо показываются комментарии к функциям. Есть навигация вперёд-назад по Cmd+Right/Left. Тела макросов показываются при наведении мышкой. Неприятный момент: если отсутствуют нужные библиотеки, их инклуды подсвечиваются красным, и после установки требуемых заголовочных файлов это уже не исправляется, пришлось перезапускать IDE. Впрочем, это мелочь.
При сборке проекта нужно сконфигурировать хитрое окошко. В качестве исполняемого файла, который будет запускаться, можно выбрать таск, определённый в make-файле:
А можно выбрать просто путь к исполняемому файлу, который появится в результате сборки:
Для отладчика мне хватило прописать “gdb”:
Вообще, я не шарю в том, как устроены make-файлы, и для меня то, как KDevelop определяет по названию таски то, что мне действительно нужно запустить, тайна. Как-нибудь, может быть, разберусь и в этой загадке мироздания.
Кнопка Build selection вроде бы должна собирать только тот проект, который у меня сейчас под курсором мыши, но почему-то собираются все проекты. Непонятно, но фиг с ним, думается, что в противном случае было бы больше проблем.
Debug запускает выбранный Launch под отладчиком. С Konsole такое почему-то не заработало, но можно было сначала нажать Execute, а потом приаттачиться к процессу. Отладчик вполне работоспособен, хотя трассировка хромает не по-детски. Лучше ставить брейкпоинты. Несколько раз вылетало в одном и том же месте (gdb слетал, программа продолжала работать) – при наведении мыши на локальную переменную, которая должна содержать строку в unicode. Потом вроде починилось, но осадок остался. Видимо, отладка ещё довольно сырая, и уповать на неё не стоит.
В целом, впечатление хорошее. Раньше я для написания мелких тестовых программ на Си пользовался CodeBlocks, теперь, наверное, буду использовать KDevelop. В первую очередь, из-за хорошей поддержки make и cmake и удобной навигации по коду.
Иногда бывает нужно решить такую задачу: есть массив, из которого мы по очереди выбираем рандомные элементы. И нужно сделать так, чтобы однажды выбранные элементы больше нам не попадались. Очевидное решение в лоб – завести рядом Set, в котором хранить либо сами выбранные элементы, либо их идентификаторы – совсем не годится: мало того, что придётся использовать дополнительную память, так ещё и нет гарантии, что следующий элемент получится найти сразу же. Чем больше мы будем выбирать элементов, тем дольше мы будем вынуждены искать следующий рандомный элемент, который еще отсутствует во множестве использованных. Другой способ – перекладывать использованные элементы в другую коллекцию – работоспособен только если исходная коллекция допускает операцию remove, и она реализована в ней эффективно. Поэтому для массивов не подходит (remove просто нет), да и для ArrayList’ов тоже не годится (remove неэффективен). Вот с LinkedList будет работать вполне себе неплохо. Смущает только невозможность восстановить исходное состояние коллекции после завершения работы алгоритма. Тогда уж проще скопировать исходную коллекцию целиком, и удалять из неё элементы. Но это не очень, если коллекция большая, а элементов нам нужно всего с десяток.
В общем, воспользуемся солдатской смекалкой и сделаем следующий алгоритм: каждый очередной выбираемый элемент мы меняем с последним элементом массива, и уменьшаем длину используемой части массива на единицу. В конце массива таким образом скапливаются “использованные” элементы. А чтобы сохранить возможность вернуться к исходному состоянию, рядом в ArrayList будем записывать оригинальные индексы использованных элементов.




Собственно, я написал класс, реализующий эту идею, и, находя его полезным, привожу код.
Пример использования:
Integer[] array = new Integer[100]; try (Picker<Integer> picker = new Picker<>(array)) { Integer randomItem = picker.pickRandom(); } |
Код класса:
Недавно я наткнулся на проблему с рендерингом console framework в стандартном эмуляторе терминала для KDE – Konsole. Проблема заключалась в том, что при перемещении окошек влево в терминале с шириной, равной или меньше ширины буфера экрана, справа от окна появлялись артефакты:

До этого я тестировал в других эмуляторах терминала (gnome-terminal, xterm, putty), и таких проблем не возникало никогда. После некоторых исследований стало ясно, что это бага в самом Konsole. Я был очень удивлён и не питал особых надежд на то, что такой баг можно легко воспроизвести, а тем более убедить мейнтейнеров проекта. Во всяком случае прикладывать к багрепорту аттач с программой на моно, которая внутри неочевидно (для мейнтейнеров) работает, имело бы мало смысла. Поэтому я решил попробовать сделать тестовую программу на чистом Си, минимального размера, но чтобы проблема была наглядно продемонстрирована. И это получилось ! Текст программы можно посмотреть в описании бага. Демонстрация проблемы была наглядна:

После этого я попросил в конференции гентоводов проверить, воспроизводится ли проблема у них. Пользователи Gentoo устанавливают одни из самых последних билдов программ, поэтому проверка у них – это важно. Оказалось, что баг действительно воспроизводится. Прошла неделя, я потихоньку уже сам стал разбираться в исходниках Konsole, научился собирать из исходников, логировать данные в момент обновления экрана, и вот сегодня – баг получил статус CONFIRMED, а значит, и некоторый шанс на то, что им кроме меня кто-то займётся.




0