LINUX.ORG.RU

XkbFreeControls glibc detected


0

2

Всем привет!

Проблема такая :

программа падает на XkbFreeControls и выдаёт glibc detected ругается на освобождение памяти внутри *** glibc detected *** free(): invalid pointer: 0x2ab48a80 ***

вот код:

void clearDescResources( XkbDescRec* desc )
{
	if ( !desc ) return;

	std::cout << "ctrls = " << desc->ctrls << "\n";
	std::cout << "names = " << desc->names << "\n";
	if ( desc->ctrls != 0 )
		XkbFreeControls( desc, XkbGroupsWrapMask, True);

	if ( desc->names != 0 )
		XkbFreeNames( desc, XkbGroupNamesMask, True);
}

в выводе указатели нормальные

в чём может быть дело? заранее спасибо


собственно корректирую метод get_layout отсюда [shell] Изменение раскладки

непонятно почему XkbDescRec desc[1]; является массивом

мои отличия - сделала не массивом и добавила проверки на 0 указателей

static int get_layout(char **pNames)
{
	Display *dpy = QX11Info::display();		// connection to the X server
	if ( dpy == 0 )
	{
		std::cout << "error: can't get display\n";
		return -1;
	}

    XkbDescRec desc;	// keyboard description 
	desc.ctrls = 0;
	desc.names = 0;
	desc.device_spec = XkbUseCoreKbd;

    if ( XkbGetControls(dpy, XkbGroupsWrapMask, &desc) != Success )
	{
		std::cout << "error get controls\n";
		clearDescResources( &desc );
		return -1;
	};

	if ( desc.ctrls == 0 )
	{
		std::cout << "null ctrls\n";
		clearDescResources( &desc );
		return -1;
	}

	if ( XkbGetNames(dpy, XkbGroupNamesMask, &desc) != Success )
	{
		std::cout << "error get names\n";
		clearDescResources( &desc );
		return -1;
	};

	if ( desc.names == 0 )
	{
		std::cout << "null names\n";
		clearDescResources( &desc );
		return -1;
	}

	Atom *atoms = desc.names->groups;
	if ( atoms == 0 )
	{
		std::cout << " null atoms\n";
		clearDescResources( &desc );
		return -1;
	}

	int gc = desc.ctrls->num_groups;
	/*
	XGetAtomNames returns a nonzero status if names are returned for all of the atoms;
	otherwise, it returns zero. 
	XGetAtomNames() can generate a BadAtom error. 
	*/
	if ( XGetAtomNames( dpy, atoms, gc, pNames) == 0 )
	{
		std::cout << "error getting atom names\n";
		clearDescResources( &desc );
		return -1;
	};

	if ( atoms == 0 || pNames == 0)
	{
		std::cout << "error get atom names\n";
		clearDescResources( &desc );
		return -1;
	}

	std::cout << "before clear resources\n";
	clearDescResources( &desc );
	std::cout << "get layout end\n";
    return gc;
}
zzkate
() автор топика
Ответ на: комментарий от zzkate

омг, какое недоверие к иксам :)

> непонятно почему XkbDescRec desc[1]; является массивом

амперсандов не люблю ;)

попробуй таки обнулять структуру memset'ом, хотя сомневаюсь, что дело в этом…

clearDescResources точно повторно не вызывается?

arsi ★★★★★
()
Ответ на: комментарий от zzkate

запускаю прогу с клиента realVNC из винды все раскладки настроены

программа вылетает на

 
if ( XkbGetControls(dpy, XkbGroupsWrapMask, &desc) != Success )
 {
 std::cout << "error get controls\n"; 
clearDescResources( &desc );
 return -1; };
 
что делать?

zzkate
() автор топика
Ответ на: комментарий от zzkate

в каком смысле «вылетает»? по «return -1», по сегфолту, по необработанному исключению иксового протокола?

arsi ★★★★★
()
Ответ на: комментарий от arsi

XkbLibraryVersion возвращает false

The XkbLibraryVersion returns False if the versions of the compile time and run time libraries are not compati- ble.

и значения lib_major_in_out = 1; lib_minor_in_out = 0;

хммм... версии либ при рантайме и при компиляции не совпадают... и что это значит?

zzkate
() автор топика
Ответ на: комментарий от zzkate

забыл сказать, что переменные перед вызовом нужно инициализировать в XkbMajorVersion и XkbMinorVersion соответственно :) 1.0 — нормальная версия, у меня такая :)

фрагмент из моей переключалки :)

        // ....
        Display *dpy = QX11Info::display();
        int major = XkbMajorVersion;
        int minor = XkbMinorVersion;
        int opcode_rtrn;
        int error_rtrn;
        int eventMask = XkbNewKeyboardNotifyMask | XkbStateNotifyMask;

        if (!XkbLibraryVersion(&major, &minor))
                qFatal("Xlib XKB extension %d.%d != %d.%d", major, minor, XkbMajorVersion, XkbMinorVersion);
        if (!XkbQueryExtension(dpy, &opcode_rtrn, &m_event, &error_rtrn, &major, &minor))
                qFatal("X server XKB extension %d.%d != %d.%d", major, minor, XkbMajorVersion, XkbMinorVersion);
        if (!XkbSelectEvents(dpy, XkbUseCoreKbd, eventMask, eventMask))
                qFatal("Couldn't select desired XKB events");
        // ....
arsi ★★★★★
()
Ответ на: комментарий от arsi

на такой код вывод получился

X server XKB extension 0.0 != 1.0 ./start.sh: line 2: 7950 бЧБТЙКОЩК ПУФБОПЧ (core dumped) LD_LIBRARY_PATH=/usr/local/src/SeaNergy/lib:/usr/local/src/library/lib ./Desktop

zzkate
() автор топика
Ответ на: комментарий от zzkate

> но ведь либа-то установлена, всё слинковалось...

есть три пары major-minor:
1) заголовочных файлов, использованных при компиляции (major-minor приложения: XkbMajorVersion, XkbMinorVersion);
2) библиотеки работы с протоколом иксов, с которой линкуется приложение (major-minor клиентской библиотеки);
3) модуля xkb сервера, к которому в данный момент подключена клиентская библиотека (major-minor модуля сервера).

XkbLibraryVersion() проверяет на соответствие ABI приложения и клиентской библиотеки иксов (1-2), которая динамически подцепилась к приложению. для неё Display* не нужен. теоретически, XkbLibraryVersion() может вернуть True даже если версии отличаются, но совместимы.

XkbQueryExtension() проверяет версии локальной библиотеки xkb и xkb-модуля сервера (2-3), к которому подключены, на совместимость.

как-то так :)

зы: man XkbQueryExtension: «In general, calls to Xkb library functions made prior to initializing the Xkb extension cause BadAccess protocol errors.» что и случилось.

arsi ★★★★★
()
Ответ на: комментарий от arsi

сам сервак не при чём - напрямую на нём всё работает как надо, а вот при доступе к нему vnc-клиента такая ерундень... хотя там с раскладками все проблемы уладили...

zzkate
() автор топика
Ответ на: комментарий от arsi

хммм... но ведь по cntrl+shift раскладка-таки переключается... значит должен же быть какой-то способ...

zzkate
() автор топика
Ответ на: комментарий от zzkate

> хммм... но ведь по cntrl+shift раскладка-таки переключается...

> а без использования XKB extension никак нельзя поменять раскладку??

что-то я совсем запутался… так раскладка переключается или нет? :)

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

arsi ★★★★★
()
Ответ на: комментарий от arsi

у меня в программе на qt есть кнопочка для переключения раскладки программа находится на сервере в linux из винды я подключаюсь vnc-клиентом к серверу и запускаю свою прогу

при нажатии ctrl+shift раскладка переключается в проге соответсвенно нет - тк нет поддержки XKB extension...

есть идея просто сымулирвоать нажатие хоткея ctrl+shift, но подозреваю что стандартная обработка не подцепится...

zzkate
() автор топика
Ответ на: комментарий от zzkate

а ещё есть одна непонятка:

из моего приложения запускается несколько дочерних процессов и им надо сообщать о том, что раскладка изменилась.

вот тут что-то похоже для винды http://www.sql.ru/forum/actualthread.aspx?bid=21&tid=447968&hl=

мне бы тоже самое для линукс найти теперь...

zzkate
() автор топика
Ответ на: комментарий от zzkate

> из моего приложения запускается несколько дочерних процессов и им надо сообщать о том, что раскладка изменилась.

зависит от того, что за приложения :)

можно элементарно им SIGUSR# послать из основного. подойдёт если они консольные и не слушают события от иксов.

если они таки висят на событиях от иксов, можно в каждом приложении «попросить» иксы, а точнее xkb, сообщать об изменении раскладки.

для приложений на Qt придётся наследоваться от QApplication и обрабатывать в x11EventFilter(), т.к. события xkb приходят на приложение, а не на окно, и перехватить его через QWidget::x11Event() не получится.

arsi ★★★★★
()
Ответ на: комментарий от arsi

приложения, которые запускаются в дочерних процессах - исковые ( текстовый редактор и калькулятор )

а как попросить xkb сообщать им об изменениях раскладки?

надо найти window по id этих дочерних процессов и ...

а вот если из приложения через system выполнить команду

setxkbmap -layout 'us,ru' -option 'grp:alt_shift_toogle,grp_led:scroll'

то раскладка сменится во всех приложениях или тоже только в моём?

zzkate
() автор топика
Ответ на: комментарий от zzkate

> а как попросить xkb сообщать им об изменениях раскладки?

1. получить идентификатор событий xkb функцией XkbQueryExtension() (в этом фрагменте он сохраняется в m_event).

2. «подписаться» функцией XkbSelectEvents() на событие XkbStateNotify (указать XkbStateNotifyMask).

3. в цикле обработки событий (или в Qt в фильтре x11EventFilter) (XEvent *event):

if (event->type == m_event) {
    XkbEvent *xe = (XkbEvent*) event;
    if (xe->any.xkb_type == XkbStateNotify) {
        // обработать изменение группы (xe->state.group)
    }
}

> раскладка сменится во всех приложениях или тоже только в моём?

это изменит набор раскладок (групп) сервера. конечно, это повлияет на все приложения.

изменение текущей группы тоже глобально для сервера, но обычно переключалки-индикаторы предоставляют возможность «сохранения» группы для приложения/окна, просто запоминая текущую группу при потере окном фокуса ввода и восстанавливают группу для другого окна при получении фокуса ввода.

arsi ★★★★★
()
Ответ на: комментарий от arsi

так это опять же получается для qt-приложения а мне надо именно для дочернего процесса чтобы где-то указатель на окно передавать или pid

zzkate
() автор топика
Ответ на: комментарий от arsi

у меня из приложения запускается 2 процесса в одном запускается блокнот, в другом калькулятор

когда я переключаю кодировку в приложении, если блокнот не запущен, то в блокноте та кодировка, которую я включила

если блокнот уже запущен и я переключаю кодировку то в блокноте она не меняется

а вот если закрыть его и открыть снова то меняется

т.е. получается что при запуске процесса информация о кодировке ему передаётся

а в то время как он запущен( блокнот ), его о смене кодировки никто не информирует, соответсвенно мне надо самой как-то сказать окну window смени кодировку ( точнее сказать xkb сказать окну )

а вопрос в том: как же это сделать?

zzkate
() автор топика
Ответ на: комментарий от zzkate

э… что-то тут не так :)

переключалка раскладки в системе есть? типа как в кде/гноме… очень похоже, что это именно она восстанавливает группу для блокнота. а когда фокус получает приложение, которого нет в базе (т.е. новое приложение), оставляет (и запоминает для него) текущую группу.

если так и есть, xkb не виноват. измени поведение переключалки на global, и она не будет привязывать раскладку к приложениям/окнам.

как вариант, можешь в своем приложении перехватывать изменения группы (переключалкой), как описано выше, и устанавливать обратно нужную.

arsi ★★★★★
()
Ответ на: комментарий от zzkate

понятно в чём дело

вместо одного конфига ~/.kde/share/config/kxkbrc в папке ~/.kde/share/config их целая куча отдельно для консоли, отдельно для десктопа, отдельно для калькулятора и блокнота

zzkate
() автор топика
Ответ на: комментарий от zzkate

причём ни в одном из них нет строчки SwitchMode=Global

даже не знаю, что тут умнее сделать? добавить во все файлы эту строку или удалить все файлы и создать kxkbrc ....

zzkate
() автор топика
Ответ на: комментарий от zzkate

да говорю же, иксы не имеют никакого отношения к привязке группы к окну/приложению, этим занимается сторонняя программа, часто по совместительству выполняющая роль индикатора раскладки. иксы умеют только глобальную раскладку.

http://forum.kde.org/viewtopic.php?f=66&t=98042 — картинка паршивая, зато на нужной вкладке: опция «Switching Policy» как раз настраивает привязку раскладки к рабочему столу (Desktop), приложению (Application), окну (Window) или отключает привязку (Global). но это для кде4. в гноме тоже должно быть что-то похожее. они настраивают не иксы/xkb, а свои менеджеры раскладок, которые, например, могут быть частью оконного менеджера…

arsi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.