英文:
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 "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;
}
Compile and run:
gcc -g -fsanitize=address code.c -o prog.exe -lX11 -lXi
./prog.exe
Output:
> 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, &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 < device_count; i++)
| ^
code.c:21:34: warning: passing argument 1 of ‘XOpenDevice’ from incompatible pointer type [-Wincompatible-pointer-types]
21 | XDevice *mouse = XOpenDevice(&dpy, mouse_id); // <-- 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(&dpy, mouse);
| ^~~~
| |
| Display **
/usr/include/X11/extensions/XInput.h:1146:5: note: expected ‘Display *’ but argument is of type ‘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
I tried this, but got the same error:
XDevice *mouse = malloc( sizeof(XDevice) );
mouse = XOpenDevice(&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
,所以不需要将&
作为指针传递(星号使其成为指针)。
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;
}
请注意,我已经移除了&
并替换了引号,以使代码更加准确。
英文:
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 &
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 "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);
// do something
XCloseDevice(dpy, mouse);
XCloseDisplay(dpy);
return 0;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论