使用X11库调用XOpenDevice时触发段错误(零页地址访问)
X11 XOpenDevice调用段错误及类型不匹配问题解决
我尝试用X11库监听特定设备事件,但调用XOpenDevice时触发段错误,编译时还出现指针类型不匹配警告。运行时提示访问零页地址,试过给XDevice分配内存、把mouse_id改成XID类型都无法解决。
原代码
#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); // <-- 段错误 // do something XCloseDevice(&dpy, mouse); XCloseDisplay(dpy); return 0; }
编译运行命令
gcc -g -fsanitize=address code.c -o prog.exe -lX11 -lXi ./prog.exe
问题根源
XListInputDevices参数错误:第二个参数要求传入int*类型的变量地址,原代码中device_count是int*,传&device_count实际是int**,导致设备数量读取错误,循环可能越界,mouse_id存在未初始化风险。XOpenDevice参数错误:第一个参数是Display*类型,原代码传了Display**(&dpy),直接导致函数内部访问非法地址,触发段错误。- 未初始化变量风险:如果未找到匹配设备,
mouse_id为随机值,后续调用会引发未定义行为。
修复后的代码
#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(NULL); if (!dpy) { fprintf(stderr, "无法打开显示连接\n"); return 1; } int device_count; XDeviceInfo *devices = XListInputDevices(dpy, &device_count); if (!devices) { fprintf(stderr, "无法获取输入设备列表\n"); XCloseDisplay(dpy); return 1; } XID mouse_id = 0; for (int i = 0; i < device_count; i++) { if (strcmp(devices[i].name, "SIGMACHIP SG 2.4G Wireless Mouse") == 0) { mouse_id = devices[i].id; break; } } XFreeDeviceList(devices); if (mouse_id == 0) { fprintf(stderr, "未找到目标鼠标设备\n"); XCloseDisplay(dpy); return 1; } printf("mouse_id: %lu\n", (unsigned long)mouse_id); XDevice *mouse = XOpenDevice(dpy, mouse_id); if (!mouse) { fprintf(stderr, "无法打开目标设备\n"); XCloseDisplay(dpy); return 1; } // 此处添加事件监听逻辑 XCloseDevice(dpy, mouse); XCloseDisplay(dpy); return 0; }
关键修复点
- 将
int *device_count改为普通int变量,XListInputDevices传入&device_count即可正确获取设备数量。 XOpenDevice第一个参数直接传dpy(Display*),而非&dpy,这是解决段错误的核心。- 初始化
mouse_id为0,添加设备未找到的判断,避免未定义行为。 - 增加
XOpenDisplay、XListInputDevices、XOpenDevice的错误检查,提升程序健壮性。
XOpenDevice文档翻译
XOpenDevice
函数原型:XDevice *XOpenDevice(Display *display, XID device_id)
功能:打开指定输入设备,返回指向XDevice结构的指针,后续操作该设备需使用此指针。
参数:
display:XOpenDisplay返回的已打开显示连接指针。device_id:待打开输入设备的ID(可通过XListInputDevices获取)。
返回值:成功返回XDevice指针;失败返回NULL,可通过XGetErrorText获取错误信息。
注意:设备使用完毕后必须调用XCloseDevice关闭,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Levi
相关产品推荐
相关产品推荐

