如何阻止xcb_image_get产生核心转储?

编程语言 2026-07-08

我想从屏幕读取像素用于屏幕录制,但遇到了一个“核心转储”错误。

构建

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

libdrm以后再说,但我在这里提一下,看看是否会引起任何问题。

test.c

// DRM
// https://github.com/ascent12/drm_doc/blob/master/01_intro/01_intro.md
// https://github.com/ascent12/drm_doc/blob/master/01_intro/src/main.c
#include <xf86drm.h>
#include <xf86drmMode.h>

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

// junk
#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){

/* Open the connection to the X server */
xcb_connection_t *c = xcb_connect (NULL, NULL);
printf("%d", xcb_connection_has_error(c)); // returns 0

/* Get the first screen */
const xcb_setup_t      *setup  = xcb_get_setup (c);
printf("%d", setup->status); // returns 1

xcb_screen_iterator_t   iter   = xcb_setup_roots_iterator (setup);
xcb_screen_t           *screen = iter.data;
printf("%d", screen->root == NULL); // returns 0


/* Create the window */
xcb_window_t window = xcb_generate_id (c);
xcb_create_window (c,                    /* Connection          */
                   XCB_COPY_FROM_PARENT,          /* depth (same as root)*/
                   window,                        /* window Id           */
                   screen->root,                  /* parent window       */
                   0, 0,                          /* x, y                */
                   150, 150,                      /* width, height       */
                   10,                            /* border_width        */
                   XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                   screen->root_visual,           /* visual              */
                   0, NULL );                     /* masks, not used yet */

xcb_generic_error_t *error = xcb_request_check(c, cook);
        if (error) {
          printf("AAA"); // "AAA" is NOT returned
        }
        free(error);

/* Map the window on the screen */
xcb_map_window (c, window);


/* Make sure commands are sent before we pause so that the window gets shown */
xcb_flush (c);

xcb_get_geometry_cookie_t  geomCookie = xcb_get_geometry (c, window);  // window is a xcb_drawable_t
xcb_get_geometry_reply_t  *geom       = xcb_get_geometry_reply (c, geomCookie, NULL); // err code last
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); // returns 0 0 150 150

// just some test schtuff
xcb_pixmap_t pix = xcb_generate_id (c);
xcb_void_cookie_t pixcook = xcb_create_pixmap (c,
               geom->depth,     /* depth of the screen */
               pix,  /* id of the pixmap */
               window,
               _width,     /* pixel width of the window */
               _height );  /* pixel height of the window */

// get image 
// 0xffffffff = https://en.wikipedia.org/wiki/4,294,967,295

xcb_map_window(c, screen->root);
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);
printf("%d", ximg->width); // ERR here: Segmentation fault (core dumped) ./test
xcb_image_get_pixel(ximg, 0, 0); 
xcb_image_destroy(ximg);

 pause ();    /* hold client until Ctrl-C */

xcb_disconnect (c);

}

我创建了一个窗口来确认xcb确实在工作。

我似乎找不到关于 xcb_image_get_pixelxcb_image_get 的太多文档,过去我把它们和 xcb_get_image 搞混过。

我还在学习,虽然在别处我也看到过Cairo可能是更好的选择,但我仍然想学习。

注x1:我在Wayland下运行最新的Ubuntu。

注x2:我尝试使用 “screen->root” 代替 “window”,反之亦然。我对测试还不太自信,仍在学习阶段,所以欢迎建议或修改。任何帮助都将不胜感激。

解决方案

好吧,我解决了!只是我还不太明白到底是怎么回事……

我把系统从Ubuntu换成了;

Linux Mint Cinnamon

机器:FUJITSU CLIENT COMPUTING LIMITED ESPRIMO G9010

操作系统 | 内核:Linux Mint 22.3 - Cinnamon 64位 | 6.14.0-37-generic

CPU | 显卡:Intel© Core™ i5-10500T CPU @ 2.30GHz × 6 | Intel Corporation CometLake-S GT2 [UHD Graphics 630]

桌面环境 | 显示服务器:Cinnamon 6.6.4 | X11

构建

# Linkages have to be after object files https://stackoverflow.com/questions/42113237/undefined-reference-when-linking-dynamic-library-in-ubuntu-system

gcc -o test test.c -I"/usr/include/libdrm" -ldrm -lxcb -lxcb-image
sudo apt-get update

sudo apt-cache search libdrm 
sudo apt-cache search xcb-image

sudo apt-get install libdrm-dev libxcb-image0-dev libxcb1-dev xcb

这些是我记得的、正在使用的库。

代码

// relevant
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <xcb/xcb.h>
#include <xcb/xcb_image.h> 

// irrelevant
#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){

/* Open the connection to the X server */
        xcb_connection_t *c = xcb_connect (NULL, NULL);
        printf("%d", xcb_connection_has_error(c));

        /* Get the first screen */
        const xcb_setup_t      *setup  = xcb_get_setup (c);
        printf("%d", setup->status);

        xcb_screen_iterator_t   iter   = xcb_setup_roots_iterator (setup);
        xcb_screen_t           *screen = iter.data;
        printf("%d", screen->root == NULL);

// https://en.wikipedia.org/wiki/4,294,967,295
        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);

    xcb_map_window(c, screen->root);

printf("%d", ximg == NULL);
        printf("%d", ximg->width);
        uint32_t p = xcb_image_get_pixel(ximg, 0, 0);
        printf("\n\n%d", p);
        xcb_image_destroy(ximg);

    xcb_disconnect (c);
}

希望有人能帮我理解。

我的最佳猜测是它和“pause”以及“xcb_flush (c);”有关——也许移动“xcb_map_window”有帮助?

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章