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

如何解决xcb_image_get引发的核心转储问题?

读取屏幕像素触发Segmentation Fault(Core Dump)问题

尝试通过XCB读取屏幕像素实现录屏功能时,触发了Segmentation Fault(core dump)错误。已确认XCB基础窗口创建功能正常,但调用xcb_image_get后访问返回的xcb_image_t结构体时崩溃,尝试过使用根窗口和自定义窗口作为参数,问题依旧。

编译命令

gcc -o test test.c -I"/usr/local/include/libdrm" -ldrm -lxcb -lxcb-image

注:libdrm为后续功能所需,此处列出供排查参考。

测试代码

// DRM
// 参考DRM文档示例
#include <xf86drm.h>
#include <xf86drmMode.h>

// XCB
#include <xcb/xcb.h>
#include <xcb/xcb_image.h> 

// 通用头文件
#include <drm_fourcc.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <stdint.h>

int main(void){

/* 连接X服务器 */
xcb_connection_t *c = xcb_connect (NULL, NULL);
printf("%d", xcb_connection_has_error(c)); // 返回0,连接正常

/* 获取第一个屏幕 */
const xcb_setup_t      *setup  = xcb_get_setup (c);
printf("%d", setup->status); // 返回1

xcb_screen_iterator_t   iter   = xcb_setup_roots_iterator (setup);
xcb_screen_t           *screen = iter.data;
printf("%d", screen->root == NULL); // 返回0,屏幕对象有效


/* 创建测试窗口 */
xcb_window_t window = xcb_generate_id (c);
xcb_void_cookie_t create_cookie = xcb_create_window (c,                    /* 连接句柄          */
                   XCB_COPY_FROM_PARENT,          /* 深度(与根窗口一致)*/
                   window,                        /* 窗口ID           */
                   screen->root,                  /* 父窗口       */
                   0, 0,                          /* 坐标x, y                */
                   150, 150,                      /* 宽高       */
                   10,                            /* 边框宽度        */
                   XCB_WINDOW_CLASS_INPUT_OUTPUT, /* 窗口类型               */
                   screen->root_visual,           /* 视觉格式              */
                   0, NULL );                     /* 属性掩码,暂未使用 */

// 检查窗口创建错误
xcb_generic_error_t *error = xcb_request_check(c, create_cookie);
if (error) {
    printf("窗口创建失败\n");
    free(error);
}

/* 映射窗口到屏幕 */
xcb_map_window (c, window);

/* 确保命令发送到服务器 */
xcb_flush (c);

// 获取窗口几何信息
xcb_get_geometry_cookie_t  geomCookie = xcb_get_geometry (c, window);
xcb_get_geometry_reply_t  *geom       = xcb_get_geometry_reply (c, geomCookie, NULL);
if (!geom) {
    printf("获取窗口几何信息失败\n");
    xcb_disconnect(c);
    return 1;
}
int _x = geom->x;
int _y = geom->y;
int _width = geom->width;
int _height = geom->height;

printf("\n %d %d %d %d\n", _x, _y, _width, _height); // 返回0 0 150 150

// 创建测试Pixmap
xcb_pixmap_t pix = xcb_generate_id (c);
xcb_void_cookie_t pixcook = xcb_create_pixmap (c,
               geom->depth,     /* 屏幕深度 */
               pix,  /* Pixmap ID */
               window,
               _width,     /* 宽度 */
               _height );  /* 高度 */

// 获取屏幕图像
// 0xffffffff 表示所有位平面
xcb_image_t* ximg = xcb_image_get(c, screen->root, 0, 0, screen->width_in_pixels, screen->height_in_pixels, 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP);
// 关键:先检查ximg是否为NULL
if (!ximg) {
    printf("xcb_image_get 调用失败\n");
    free(geom);
    xcb_disconnect(c);
    return 1;
}
printf("%d\n", ximg->width); 

uint32_t pixel = xcb_image_get_pixel(ximg, 0, 0); 
printf("像素值:%u\n", pixel);

xcb_image_destroy(ximg);
free(geom);

pause ();    /* 等待Ctrl-C退出 */

xcb_disconnect (c);
return 0;
}

补充信息

  • 运行环境:最新版Ubuntu,Wayland显示服务器
  • 混淆过xcb_image_get和xcb_get_image,找不到xcb_image_get和xcb_image_get_pixel的详细文档
  • 了解Cairo可能是更便捷的方案,但希望学习XCB原生用法

问题分析与修复建议

  1. 直接崩溃原因:未检查xcb_image_get返回值
    xcb_image_get在调用失败时会返回NULL,直接访问ximg->width会触发段错误。必须先判断返回值是否为NULL,再进行后续操作。

  2. Wayland环境的兼容性问题
    在Wayland下,XCB是通过XWayland兼容层运行的,无法直接捕获Wayland的全局屏幕内容。XWayland的根窗口仅对应X兼容应用的区域,而非整个屏幕。如果要捕获Wayland屏幕,建议使用Wayland原生API或工具库;如果坚持用XCB,需确保目标窗口是XWayland管理的窗口。

  3. 代码中的其他问题修复

    • 原代码中xcb_request_check(c, cook)里的cook未定义,已修改为对应窗口创建的create_cookie
    • 添加了xcb_get_geometry_reply的返回值NULL判断
    • 补充了xcb_get_geometry_reply的内存释放操作

内容的提问来源于stack exchange,提问作者Loki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.06 16:24:49