You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

问题根源

  1. XListInputDevices参数错误:第二个参数要求传入int*类型的变量地址,原代码中device_count是int*,传&device_count实际是int**,导致设备数量读取错误,循环可能越界,mouse_id存在未初始化风险。
  2. XOpenDevice参数错误:第一个参数是Display*类型,原代码传了Display**(&dpy),直接导致函数内部访问非法地址,触发段错误。
  3. 未初始化变量风险:如果未找到匹配设备,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 10:22:42