Автор Тема: XOpenDisplay  (Прочитано 386 раз)

Оффлайн magicwolf

  • Начинающий
  • *
  • Сообщений: 22
XOpenDisplay
« : 11.09.2023 08:50:06 »
Здравствуйте!

Компилирую xopen.c:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <string.h>

void poll ( unsigned short n )
{
  printf("poll=%d\n",n);
}

int main ( void )
{
  Display * display;

  display = XOpenDisplay ( NULL );
  if ( display==NULL )
    printf("XOpenDisplay - error!\n");
  else {
    printf("XOpenDisplay - OK!\n");
    XCloseDisplay ( display );
  }
  return 0;
}

C помощью команды:
gcc -o xopen ./xopen.c -Wall -lX11

Запускаю xopen, и получаю бесконечный цикл вызова функции poll. В чем может быть проблема?


Сергей

Оффлайн ruslandh

  • Поспешай не торопясь !
  • Модератор глобальный
  • *****
  • Сообщений: 32 251
  • Учиться .... Телепатами не рождаются, ими ....
    • Email
Re: XOpenDisplay
« Ответ #1 : 11.09.2023 10:14:19 »
А где функция main ?

Оффлайн magicwolf

  • Начинающий
  • *
  • Сообщений: 22
Re: XOpenDisplay
« Ответ #2 : 11.09.2023 10:17:40 »
int main ( void )
{
  Display * display

Оффлайн magicwolf

  • Начинающий
  • *
  • Сообщений: 22
Re: XOpenDisplay
« Ответ #3 : 11.09.2023 10:19:19 »
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <string.h>

void poll ( unsigned short n )
{
  printf("poll=%d\n",n);
}

int main ( int argc, char ** argv )
{
  Display * display;

  display = XOpenDisplay ( NULL );
  if ( display==NULL )
    printf("XOpenDisplay - error!\n");
  else {
    printf("XOpenDisplay - OK!\n");
    XCloseDisplay ( display );
  }
  return 0;
}

Оффлайн toreonify

  • Давно тут
  • **
  • Сообщений: 77
Re: XOpenDisplay
« Ответ #4 : 11.09.2023 11:55:06 »
void poll ( unsigned short n )
{
  printf("poll=%d\n",n);
}
Не знаю, куда смотрел компилятор, но poll - это системный вызов ядра. Вы его переопределили и остальные библиотеки не могут получить корректного ответа.
https://linux.die.net/man/2/poll

Переименуйте функцию и программа завершится успешно.

Оффлайн magicwolf

  • Начинающий
  • *
  • Сообщений: 22
Re: XOpenDisplay
« Ответ #5 : 11.09.2023 12:27:44 »
Функцию я конечно переименовал, не проблема. Проблема в том, что компилятор не ругается и мне непонятно какие еще функции надо переименовать, чтобы таких коллизий не было.

Оффлайн toreonify

  • Давно тут
  • **
  • Сообщений: 77
Re: XOpenDisplay
« Ответ #6 : 11.09.2023 13:56:50 »
Чтобы наверняка - используйте префикс к названиям функций (почитайте исходники больших проектов на C). Можно использовать параметр -fvisibility=hidden, но это не самое лаконичное решение, особенно при отладке. К сожалению, линковщик так работает при появлении двух и более одинаковых символов. Возможно, что использование линковщика отдельно от компилятора может исключить эту проблему с использованием дополнительных параметров.

мне непонятно какие еще функции надо переименовать, чтобы таких коллизий не было.
Читать список стандартных символов библиотеки C: https://www.gnu.org/software/libc/manual/pdf/libc.pdf - страница 1184 (функции), страница 1181 (типы).

Оффлайн magicwolf

  • Начинающий
  • *
  • Сообщений: 22
Re: XOpenDisplay
« Ответ #7 : 11.09.2023 15:04:51 »
Не важно буду я использовать префикс (постфикс) или нет, может совпасть. Анализировать имена стандартных функций и функций в проекте, которых сотни, это не реально. Проблема не в этом. Линкер сообщил бы, если я в проекте использовал стандартную функцию и свою с одинаковыми именами, а тут он не сообщает, значит, скорее всего, проблема происходит когда динамически подключается библиотека, а не статически.

Оффлайн toreonify

  • Давно тут
  • **
  • Сообщений: 77
Re: XOpenDisplay
« Ответ #8 : 11.09.2023 15:55:21 »
Линкер сообщил бы, если я в проекте использовал стандартную функцию и свою с одинаковыми именами
Вот в этом вы заблуждаетесь. Вас может предупредить только компилятор, если увидит два конфликтных определения функции в заголовочных файлах или исходном коде.

Например:

#include <poll.h> // Заголовочный файл с настоящей функций poll

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

void poll ( unsigned short n ); // Определение функции

int main ( int argc, char ** argv )
{
  Display * display;

  display = XOpenDisplay ( NULL );
  if ( display==NULL )
    printf("XOpenDisplay - error!\n");
  else {
    printf("XOpenDisplay - OK!\n");
    XCloseDisplay ( display );
  }
  return 0;
}

void poll ( unsigned short n ) // Реализация функции
{
  printf("poll=%d\n",n);
}


$ gcc -o xopen -lX11 ./xopen.c -Wall
./xopen.c:10:6: error: conflicting types for ‘poll’
   10 | void poll ( unsigned short n );
      |      ^~~~
In file included from /usr/include/poll.h:1,
                 from ./xopen.c:1:
/usr/include/sys/poll.h:54:12: note: previous declaration of ‘poll’ was here
   54 | extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);
      |            ^~~~
./xopen.c:26:6: error: conflicting types for ‘poll’
   26 | void poll ( unsigned short n )
      |      ^~~~
In file included from /usr/include/poll.h:1,
                 from ./xopen.c:1:
/usr/include/sys/poll.h:54:12: note: previous declaration of ‘poll’ was here
   54 | extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);
      |            ^~~~


Вот тут есть большой разбор про конфликт версий динамических библиотек. В разделе "toy example" как раз похожий сценарий на ваш.
https://trofi.github.io/posts/248-how-do-shared-library-collisions-break.html

Конфликт был бы замечен, если бы вы линковали статическую версию библиотеки. Так как у вас динамические библиотеки - увы. Иначе, никакие бы обманки как DXVK просто не работали. Они бы не смогли переопределить символы.

Например:

xopen2.c:
#include <stdio.h>

void poll ( unsigned short n )
{
  printf("poll=%d\n",n);
}

$ gcc -o libxopen2.a -c xopen2.c
$ gcc -o xopen ./xopen.c -lX11 -lxopen2 -L. -Wall
ld: ./libxopen2.a: в функции «poll»:
xopen2.c:(.text+0x0): повторное определение «poll»; /tmp/.private/korytov_ip/ccG0vVhN.o:xopen.c:(.text+0x0): здесь первое определение
collect2: error: ld returned 1 exit status

Оффлайн magicwolf

  • Начинающий
  • *
  • Сообщений: 22
Re: XOpenDisplay
« Ответ #9 : 11.09.2023 15:59:50 »
Я нигде не использую стандартную функцию poll. Про статические либы:
https://forum.altlinux.org/index.php?topic=47372.msg380172#msg380172
По идее, когда происходит загрузка функции из динамической либы, то получается указатель на нее. Этот указатель ни как не может быть связан с какой-то моей функцией.

« Последнее редактирование: 11.09.2023 16:02:06 от magicwolf »

Оффлайн toreonify

  • Давно тут
  • **
  • Сообщений: 77
Re: XOpenDisplay
« Ответ #10 : 11.09.2023 16:58:49 »
Про статические либы:
Я не говорю вам или разработчикам дистрибутива собирать статические библиотеки) Я лишь привел пример, когда компилятор уж точно вам скажет, что есть коллизия имен функций.

По идее, когда происходит загрузка функции из динамической либы, то получается указатель на нее. Этот указатель ни как не может быть связан с какой-то моей функцией.
Если она запускается, значит кто-то (линковщик или _start в стандартной библиотеке C) переопределил указатель или выбрал другой из списка символов :) Компьютер же делает то, что ему сказали. А то, что мы не знаем полностью как работает процесс компиляции и динамического вызова функций - наша проблема.