我想做一个非常简单的电视面板测试仪。有了这个answer about SDL2 without X,我就可以用Raspberry Pi Zero准备这种测试仪,并且效果很好。
运行时,我只能在电视之间切换电缆,并且在经过测试的电视上,我的绿屏非常快。
但是,当我运行程序而未在HDMI上连接任何设备时,出现分段错误。

这是代码:

#include <SDL.h>
#include <iostream>

int main( int argc, char** argv )
{

    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
    {
        std::cerr << "SDL_Init(): " << SDL_GetError() << '\n';
        return EXIT_FAILURE;
    }

    SDL_Window* window = SDL_CreateWindow
        (
        "SDL2",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        1920, 1080,
        SDL_WINDOW_SHOWN
        );
    if( nullptr == window )
    {
        std::cerr << "SDL_CreateWindow(): " << SDL_GetError() << '\n';
        return EXIT_FAILURE;
    }

    SDL_Renderer* renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
    if( nullptr == renderer )
    {
        std::cerr << "SDL_CreateRenderer(): " << SDL_GetError() << '\n';
        return EXIT_FAILURE;
    }

    bool running = true;
    while( running )
    {
        SDL_Event ev;
        while( SDL_PollEvent( &ev ))
        {
            if( ev.type == SDL_QUIT )
            {
                running = false;
            }
        }

        SDL_SetRenderDrawColor( renderer, 0x00, 0xff, 0x00, SDL_ALPHA_OPAQUE );
        SDL_RenderClear( renderer );
        SDL_RenderPresent( renderer );
    }

    SDL_DestroyRenderer( renderer );
    SDL_DestroyWindow( window );
    SDL_Quit();
    return 0;
}

这是此程序的strace的结尾:
close(5)                                = 0
openat(AT_FDCWD, "/usr/share/drirc.d/00-mesa-defaults.conf", O_RDONLY|O_LARGEFILE) = 5
read(5, "<?xml version=\"1.0\" standalone=\""..., 4096) = 4096
getrandom("\x26\x27\xac\x36", 4, GRND_NONBLOCK) = 4
read(5, ">\n\n        <application name=\"Un"..., 4096) = 4096
read(5, "_glsl_abs_sqrt\" value=\"true\" />\n"..., 4096) = 4096
read(5, "ation>\n\n        <application nam"..., 4096) = 4096
read(5, "daptive_sync\" value=\"false\" />\n "..., 4096) = 4096
read(5, "ation>\n        <application name"..., 4096) = 4096
read(5, "executable=\"dota2\">\n            "..., 4096) = 1062
read(5, "", 4096)                       = 0
close(5)                                = 0
openat(AT_FDCWD, "/etc/drirc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pi/.drirc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
ioctl(4, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb98e0) = 0
fcntl64(4, F_DUPFD_CLOEXEC, 3)          = 5
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_GET_CAP, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9898) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb98a8) = 0
gettimeofday({tv_sec=1582731761, tv_usec=164921}, NULL) = 0
openat(AT_FDCWD, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 6
read(6, "0\n", 8192)                    = 2
close(6)                                = 0
openat(AT_FDCWD, "/proc/self/auxv", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 6
read(6, "\20\0\0\0\326\201\0\0", 8)     = 8
close(6)                                = 0
futex(0xb5f4e3d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
ioctl(5, DRM_IOCTL_TEGRA_GET_SYNCPT_BASE or DRM_IOCTL_VC4_GET_TILING, 0xbecb9860) = -1 ENOENT (No such file or directory)
ioctl(3, DRM_IOCTL_GET_CAP, 0xbecb9910) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(3, DRM_IOCTL_MODE_GETRESOURCES, 0xbecba340) = 0
ioctl(3, DRM_IOCTL_MODE_GETRESOURCES, 0xbecba340) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
close(5)                                = 0
close(4)                                = 0
munmap(0xb50af000, 17353000)            = 0
munmap(0xb14ea000, 115624)              = 0
munmap(0xb14cf000, 106672)              = 0
munmap(0xb14a5000, 168220)              = 0
munmap(0xb148d000, 94536)               = 0
munmap(0xb1476000, 90356)               = 0
close(3)                                = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x4} ---
+++ killed by SIGSEGV +++
Segmentation fault

这是config.txt hdmi_并显示相关部分:
framebuffer_width=1920
framebuffer_height=1080
hdmi_force_hotplug=1
hdmi_ignore_edid=0xa5000080
hdmi_edid_file=1
hdmi_ignore_edid_audio=1
hdmi_force_edid_3d=1
hdmi_ignore_cec_init=1
hdmi_ignore_cec=1
hdmi_pixel_encoding=2
hdmi_blanking=0
edid_content_type=0
hdmi_group=1
hdmi_mode=16
hdmi_force_mode=1
dtoverlay=vc4-kms-v3d

我该如何解决这个问题?

在连接第一台设备之前,我可以作为虚拟HDMI输出运行吗?

因为我想使该测试仪成为无头自动启动设备,并且因为在连接任何HDMI输出之前将其打开(因为启动rPi-Zero速度很慢-甚至是极简版本)。

[编辑]

full version of sample app的输出:
Testing video drivers...
SDL_VIDEODRIVER available: x11 KMSDRM RPI dummy
SDL_VIDEODRIVER usable   : KMSDRM
SDL_VIDEODRIVER selected : KMSDRM
SDL_RENDER_DRIVER available: opengles2 opengles software
SDL_RENDER_DRIVER selected : opengles2

这是我从gdb得到的:
Starting program: /home/pi/hdmitester/minimal
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
[New Thread 0xb6a8d450 (LWP 645)]

Thread 1 "minimal" received signal SIGSEGV, Segmentation fault.
KMSDRM_VideoQuit (_this=<optimized out>) at /usr/src/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c:665
665         if (dispdata->conn) {
(gdb) bt
#0  KMSDRM_VideoQuit (_this=<optimized out>) at /usr/src/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c:665
#1  0xb6f40174 in SDL_VideoQuit_REAL () at /usr/src/SDL/src/video/SDL_video.c:2869
#2  0xb6f40c38 in SDL_VideoQuit_REAL () at /usr/src/SDL/src/video/SDL_video.c:2853
#3  SDL_VideoInit_REAL (driver_name=<optimized out>) at /usr/src/SDL/src/video/SDL_video.c:533
#4  0xb6e9d63c in SDL_InitSubSystem_REAL (flags=62001) at /usr/src/SDL/src/SDL.c:206
#5  0x00010aac in main ()

最佳答案

正如@genpfault在评论中指出的那样,SDL ver。 2.0.10解决了不存在HDMI设备时的分段错误。
因此,如果有人使用hg clone ...git clone ...,请确保在构建自己的版本之前切换到SDL2源的正确版本。

关于c++ - 如果未连接HDMI设备,则不带X的SDL2会显示 'Segmentation fault',我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60432999/

10-08 23:38