segmentation fault在C中,地址指向零页 – XOpenDevice

huangapple go评论73阅读模式
英文:

segmentation fault in C, address points to zero page - XOpenDevice

问题

我正在尝试使用X11库来监视特定设备的事件,但在XOpenDevice处遇到问题。

#include "stdio.h"
#include <stdlib.h>
#include "string.h"
#include "X11/extensions/XInput.h"
#include "X11/Xlib.h"

int main(int argc, char *argv[])
{
    Display *dpy = XOpenDisplay(0);

    int *device_count;
    XDeviceInfo *devices = XListInputDevices(dpy, &device_count);

    int mouse_id;
    for (int i = 0; i < device_count; i++)
        if (0 == strcmp(devices[i].name, "SIGMACHIP SG 2.4G Wireless Mouse"))
            mouse_id = devices[i].id;
    XFreeDeviceList(devices);
    printf("mouse_id: %d\n", mouse_id);

    XDevice *mouse = XOpenDevice(&dpy, mouse_id); // <-- segmentation fault
    // do something
    XCloseDevice(&dpy, mouse);

    XCloseDisplay(dpy);
    return 0;
}

编译并运行:

gcc -g -fsanitize=address code.c -o prog.exe -lX11 -lXi
./prog.exe

输出:

gcc -g -fsanitize=address code.c -o prog.exe -lX11 -lXi
code.c: 在函数‘main’中:
code.c:12:51: 警告:从不兼容的指针类型传递参数 2 给‘XListInputDevices’ [-Wincompatible-pointer-types]
   12 |     XDeviceInfo *devices = XListInputDevices(dpy, &device_count);
      |                                                   ^~~~~~~~~~~~~
      |                                                   |
      |                                                   int **
In file included from code.c:4:
/usr/include/X11/extensions/XInput.h:1133:5: 注意:预期‘int *’,但参数的类型是‘int **’
 1133 |     int*                /* ndevices */
      |     ^~~~
code.c:15:23: 警告:指针和整数之间的比较
   15 |     for (int i = 0; i < device_count; i++)
      |                       ^
code.c:21:34: 警告:从不兼容的指针类型传递参数 1 给‘XOpenDevice’ [-Wincompatible-pointer-types]
   21 |     XDevice *mouse = XOpenDevice(&dpy, mouse_id); // <-- segmentation fault
      |                                  ^~~~
      |                                  |
      |                                  Display **
/usr/include/X11/extensions/XInput.h:1141:5: 注意:预期‘Display *’,但参数的类型是‘Display **’
 1141 |     Display*            /* display */,
      |     ^~~~~~~~
code.c:23:18: 警告:从不兼容的指针类型传递参数 1 给‘XCloseDevice’ [-Wincompatible-pointer-types]
   23 |     XCloseDevice(&dpy, mouse);
      |                  ^~~~
      |                  |
      |                  Display **
/usr/include/X11/extensions/XInput.h:1146:5: 注意:预期‘Display *’,但参数的类型是‘Display **’
 1146 |     Display*            /* display */,
      |     ^~~~~~~~

./prog.exe
mouse_id: 10
AddressSanitizer:DEADLYSIGNAL
=================================================================
==28208==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000048 (pc 0x7ffba8d03613 bp 0x000000000008 sp 0x7ffdf9cfb420 T0)
==28208==The signal is caused by a READ memory access.
==28208==Hint: address points to the zero page.
    #0 0x7ffba8d03613 in _XFlush (/lib64/libX11.so.6+0x49613) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418)
    #1 0x7ffba8d038e4 in _XGetRequest (/lib64/libX11.so.6+0x498e4) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418)
    #2 0x7ffba8cf565e in XQueryExtension (/lib64/libX11.so.6+0x3b65e) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418)
    #3 0x7ffba951a800  (/lib64/libXi.so.6+0x3800) (BuildId: ee64e5f4d60239d9dcab6326d02bd5c2c6e31259)
    #4 0x7ffba9521d68 in XOpenDevice (/lib64/libXi.so.6+0xad68) (BuildId: ee64e5f4d60239d9dcab6326d02bd5c2c6e31259)
    #5 0x401430 in main /home/levi/development/mouse-chording/code.c:21
    #6 0x7ffba8ae4bef in __libc_start_call_main (/lib64/libc.so.6+0x27bef) (BuildId: 7ed2a863c9bc5e582a36387b1b1f26053e10ef16)
    #7 0x7ffba8ae4cb8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x27cb8) (BuildId: 7ed2a863c9bc5e582a36387b1b1f26053e10ef16)
    #8 0x401154 in _start ../sysdeps/x86_64/start.S:115

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib64/libX11.so.6+0x49613) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418) in _XFlush
==28208==ABORTING

我尝试过以下方法,但仍然遇到相同的错误:

XDevice *mouse = malloc(sizeof(XDevice));
mouse = XOpenDevice(&dpy, mouse_id);

我还尝试将int mouse_id更改为XID mouse_id以更接近API,但仍然出现相同的错误。

我已经查看了使用相同API的存储库,试图找到差异,但似乎我与其他人做

英文:

I'm trying to use the X11 library to look at events from a specific device, but getting stuck at XOpenDevice.

The code:

#include &quot;stdio.h&quot;
#include &lt;stdlib.h&gt;
#include &quot;string.h&quot;
#include &quot;X11/extensions/XInput.h&quot;
#include &quot;X11/Xlib.h&quot;

int main(int argc, char *argv[])
{
    Display *dpy = XOpenDisplay(0);

    int *device_count;
    XDeviceInfo *devices = XListInputDevices(dpy, &amp;device_count);

    int mouse_id;
    for (int i = 0; i &lt; device_count; i++)
        if (0 == strcmp(devices[i].name, &quot;SIGMACHIP SG 2.4G Wireless Mouse&quot;))
            mouse_id = devices[i].id;
    XFreeDeviceList(devices);
    printf(&quot;mouse_id: %d\n&quot;, mouse_id);

    XDevice *mouse = XOpenDevice(&amp;dpy, mouse_id); // &lt;-- segmentation fault
    // do something
    XCloseDevice(&amp;dpy, mouse);

    XCloseDisplay(dpy);
    return 0;
}

Compile and run:

gcc -g -fsanitize=address code.c -o prog.exe -lX11 -lXi
./prog.exe

Output:

&gt; gcc -g -fsanitize=address code.c -o prog.exe -lX11 -lXi
code.c: In function ‘main’:
code.c:12:51: warning: passing argument 2 of ‘XListInputDevices’ from incompatible pointer type [-Wincompatible-pointer-types]
   12 |     XDeviceInfo *devices = XListInputDevices(dpy, &amp;device_count);
      |                                                   ^~~~~~~~~~~~~
      |                                                   |
      |                                                   int **
In file included from code.c:4:
/usr/include/X11/extensions/XInput.h:1133:5: note: expected ‘int *’ but argument is of type ‘int **’
 1133 |     int*                /* ndevices */
      |     ^~~~
code.c:15:23: warning: comparison between pointer and integer
   15 |     for (int i = 0; i &lt; device_count; i++)
      |                       ^
code.c:21:34: warning: passing argument 1 of ‘XOpenDevice’ from incompatible pointer type [-Wincompatible-pointer-types]
   21 |     XDevice *mouse = XOpenDevice(&amp;dpy, mouse_id); // &lt;-- segmentation fault
      |                                  ^~~~
      |                                  |
      |                                  Display **
/usr/include/X11/extensions/XInput.h:1141:5: note: expected ‘Display *’ but argument is of type ‘Display **’
 1141 |     Display*            /* display */,
      |     ^~~~~~~~
code.c:23:18: warning: passing argument 1 of ‘XCloseDevice’ from incompatible pointer type [-Wincompatible-pointer-types]
   23 |     XCloseDevice(&amp;dpy, mouse);
      |                  ^~~~
      |                  |
      |                  Display **
/usr/include/X11/extensions/XInput.h:1146:5: note: expected ‘Display *’ but argument is of type ‘Display **’
 1146 |     Display*            /* display */,
      |     ^~~~~~~~

&gt; ./prog.exe
mouse_id: 10
AddressSanitizer:DEADLYSIGNAL
=================================================================
==28208==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000048 (pc 0x7ffba8d03613 bp 0x000000000008 sp 0x7ffdf9cfb420 T0)
==28208==The signal is caused by a READ memory access.
==28208==Hint: address points to the zero page.
    #0 0x7ffba8d03613 in _XFlush (/lib64/libX11.so.6+0x49613) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418)
    #1 0x7ffba8d038e4 in _XGetRequest (/lib64/libX11.so.6+0x498e4) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418)
    #2 0x7ffba8cf565e in XQueryExtension (/lib64/libX11.so.6+0x3b65e) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418)
    #3 0x7ffba951a800  (/lib64/libXi.so.6+0x3800) (BuildId: ee64e5f4d60239d9dcab6326d02bd5c2c6e31259)
    #4 0x7ffba9521d68 in XOpenDevice (/lib64/libXi.so.6+0xad68) (BuildId: ee64e5f4d60239d9dcab6326d02bd5c2c6e31259)
    #5 0x401430 in main /home/levi/development/mouse-chording/code.c:21
    #6 0x7ffba8ae4bef in __libc_start_call_main (/lib64/libc.so.6+0x27bef) (BuildId: 7ed2a863c9bc5e582a36387b1b1f26053e10ef16)
    #7 0x7ffba8ae4cb8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x27cb8) (BuildId: 7ed2a863c9bc5e582a36387b1b1f26053e10ef16)
    #8 0x401154 in _start ../sysdeps/x86_64/start.S:115

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib64/libX11.so.6+0x49613) (BuildId: db539db0970427ed0cb836eae3d193c23fc94418) in _XFlush
==28208==ABORTING

I tried this, but got the same error:

XDevice *mouse = malloc( sizeof(XDevice) );
mouse = XOpenDevice(&amp;dpy, mouse_id);

I tried changing int mouse_id to XID mouse_id to more closely match the API, but same error.

I've looked up repos using the same API, trying to find differences, but it seems like I am doing the same as everybody else. Example: https://github.com/FreeRDP/FreeRDP/blob/10386e73bcebd450062a9ef5272260af5b621d05/client/X11/xf_client.c#L991C1-L991C59

Have barely used C before, so I am not sure where to go from here.

Relevant docs: https://x.org/releases/X11R7.7/doc/libXi/inputlib.html#XOpenDevice

答案1

得分: 1

如@someprogrammerdude指出的,问题是关于指针的误解。

因为dpy被初始化为指针,使用Display *dpy,所以不需要将&amp;作为指针传递(星号使其成为指针)。

device_count则有相反的问题。

这是修复后的版本示例:

#include "stdio.h"
#include "string.h"
#include "X11/extensions/XInput.h"
#include "X11/Xlib.h"

int main(int argc, char *argv[])
{
    Display *dpy = XOpenDisplay(0);

    int device_count;
    XDeviceInfo *devices;
    devices = XListInputDevices(dpy, &device_count);

    int mouse_id;
    for (int i = 0; i < device_count; i++)
        if (0 == strcmp(devices[i].name, "SIGMACHIP SG 2.4G Wireless Mouse"))
            mouse_id = devices[i].id;
    XFreeDeviceList(devices);
    printf("mouse_id: %d\n", mouse_id);

    XDevice *mouse = XOpenDevice(dpy, mouse_id);
    // 做一些操作
    XCloseDevice(dpy, mouse);

    XCloseDisplay(dpy);
    return 0;
}

请注意,我已经移除了&amp;并替换了引号,以使代码更加准确。

英文:

as pointed out by @someprogrammerdude, the problem was a misunderstanding around pointers.

since dpy was initialized as a pointer with Display *dpy it did not need the &amp; to be passed as a pointer (the asterix makes it a pointer).

device_count had the opposite problem.

and this is what the fixed version looks like.

#include &quot;stdio.h&quot;
#include &quot;string.h&quot;
#include &quot;X11/extensions/XInput.h&quot;
#include &quot;X11/Xlib.h&quot;

int main(int argc, char *argv[])
{
    Display *dpy = XOpenDisplay(0);

    int device_count;
    XDeviceInfo *devices;
    devices = XListInputDevices(dpy, &amp;device_count);

    int mouse_id;
    for (int i = 0; i &lt; device_count; i++)
        if (0 == strcmp(devices[i].name, &quot;SIGMACHIP SG 2.4G Wireless Mouse&quot;))
            mouse_id = devices[i].id;
    XFreeDeviceList(devices);
    printf(&quot;mouse_id: %d\n&quot;, mouse_id);

    XDevice *mouse = XOpenDevice(dpy, mouse_id);
    // do something
    XCloseDevice(dpy, mouse);

    XCloseDisplay(dpy);
    return 0;
}

huangapple
  • 本文由 发表于 2023年7月31日 19:43:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803280.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定