Мне сказали, что EGL — хороший выбор для рендеринга графики в окне Wayland. Я еще не уверен и до сих пор не знаю, является ли (кроме вулкана) единственным способом чтобы использовать магию OpenGL в оконном клиенте Wayland.
Я попробовал и с первых строк решил столкнуться с утечками памяти.
Вот make-файл:
WAYLAND_FLAGS = `pkg-config wayland-client wayland-egl --cflags --libs`
GL_FLAGS = `pkg-config egl glesv2 --cflags --libs`
CGLM_FLAGS = `pkg-config cglm --cflags --libs` -lm
WAYLAND_PROTOCOLS_DIR = `pkg-config wayland-protocols --variable=pkgdatadir`
WAYLAND_SCANNER = `pkg-config --variable=wayland_scanner wayland-scanner`
CFLAGS = -std=c11 -Wall -Werror -g
XDG_SHELL_PROTOCOL = $(WAYLAND_PROTOCOLS_DIR)/stable/xdg-shell/xdg-shell.xml
XDG_SHELL_FILES=xdg-shell-client-protocol.h xdg-shell-protocol.c
all: hello-wayland
hello-wayland: main.c $(XDG_SHELL_FILES)
$(CC) $(CFLAGS) -o hello-wayland $(WAYLAND_FLAGS) $(GL_FLAGS) $(CGLM_FLAGS) *.c
xdg-shell-client-protocol.h:
$(WAYLAND_SCANNER) client-header $(XDG_SHELL_PROTOCOL) xdg-shell-client-protocol.h
xdg-shell-protocol.c:
$(WAYLAND_SCANNER) code $(XDG_SHELL_PROTOCOL) xdg-shell-protocol.c
.PHONY: clean
clean:
$(RM) hello-wayland $(XDG_SHELL_FILES)
Вот код перед EGL:
#include <cglm/cglm.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <wayland-client.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>
#include "xdg-shell-client-protocol.h"
int main(int argc, char *argv[]) {
struct wl_display *display = wl_display_connect(0);
printf("Display : %p\n", display);
if (display) wl_display_disconnect(display);
printf("Display disconnected\n");
return 0;
}
Нет утечки памяти:
==10344== Memcheck, a memory error detector
==10344== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==10344== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==10344== Command: ./hello-wayland
==10344==
Display : 0x4c31890
Display disconnected
==10344==
==10344== HEAP SUMMARY:
==10344== in use at exit: 0 bytes in 0 blocks
==10344== total heap usage: 61 allocs, 61 frees, 20,039 bytes allocated
==10344==
==10344== All heap blocks were freed -- no leaks are possible
==10344==
==10344== For lists of detected and suppressed errors, rerun with: -s
==10344== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
И когда я добавляю немного EGL:
int main(int argc, char *argv[]) {
struct wl_display *display = wl_display_connect(0);
EGLDisplay egl_display;
printf("Display : %p\n", display);
egl_display = eglGetDisplay((EGLNativeDisplayType) display);
printf("EGL display : %p\n", egl_display);
if (egl_display != EGL_NO_DISPLAY) eglTerminate(egl_display);
printf("EGL disconnected\n");
if (display) wl_display_disconnect(display);
printf("Display disconnected\n");
return 0;
}
Я получил это:
==10430== Memcheck, a memory error detector
==10430== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==10430== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==10430== Command: ./hello-wayland
==10430==
Display : 0x4c31890
EGL display : 0x4c508c0
EGL disconnected
Display disconnected
==10430==
==10430== HEAP SUMMARY:
==10430== in use at exit: 28,526 bytes in 68 blocks
==10430== total heap usage: 176 allocs, 108 frees, 125,398 bytes allocated
==10430==
==10430== 24 bytes in 1 blocks are still reachable in loss record 1 of 8
==10430== at 0x484282F: malloc (vg_replace_malloc.c:446)
==10430== by 0x402587F: malloc (rtld-malloc.h:56)
==10430== by 0x402587F: strdup (strdup.c:42)
==10430== by 0x4014B48: _dl_load_cache_lookup (dl-cache.c:515)
==10430== by 0x4008F1F: _dl_map_object (dl-load.c:2116)
==10430== by 0x400C9CB: dl_open_worker_begin (dl-open.c:578)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430== by 0x4A49E23: dlopen_doit (dlopen.c:56)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4001678: _dl_catch_error (dl-catch.c:256)
==10430==
==10430== 24 bytes in 1 blocks are still reachable in loss record 2 of 8
==10430== at 0x484282F: malloc (vg_replace_malloc.c:446)
==10430== by 0x400BE90: UnknownInlinedFun (rtld-malloc.h:56)
==10430== by 0x400BE90: _dl_new_object (dl-object.c:199)
==10430== by 0x4007299: _dl_map_object_from_fd (dl-load.c:1053)
==10430== by 0x4008CB7: _dl_map_object (dl-load.c:2249)
==10430== by 0x400C9CB: dl_open_worker_begin (dl-open.c:578)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430== by 0x4A49E23: dlopen_doit (dlopen.c:56)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4001678: _dl_catch_error (dl-catch.c:256)
==10430==
==10430== 367 bytes in 16 blocks are still reachable in loss record 3 of 8
==10430== at 0x484282F: malloc (vg_replace_malloc.c:446)
==10430== by 0x402587F: malloc (rtld-malloc.h:56)
==10430== by 0x402587F: strdup (strdup.c:42)
==10430== by 0x4014B48: _dl_load_cache_lookup (dl-cache.c:515)
==10430== by 0x4008F1F: _dl_map_object (dl-load.c:2116)
==10430== by 0x400287C: openaux (dl-deps.c:64)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4002CDF: _dl_map_object_deps (dl-deps.c:232)
==10430== by 0x400CA34: dl_open_worker_begin (dl-open.c:638)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430==
==10430== 367 bytes in 16 blocks are still reachable in loss record 4 of 8
==10430== at 0x484282F: malloc (vg_replace_malloc.c:446)
==10430== by 0x400BE90: UnknownInlinedFun (rtld-malloc.h:56)
==10430== by 0x400BE90: _dl_new_object (dl-object.c:199)
==10430== by 0x4007299: _dl_map_object_from_fd (dl-load.c:1053)
==10430== by 0x4008CB7: _dl_map_object (dl-load.c:2249)
==10430== by 0x400287C: openaux (dl-deps.c:64)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4002CDF: _dl_map_object_deps (dl-deps.c:232)
==10430== by 0x400CA34: dl_open_worker_begin (dl-open.c:638)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430==
==10430== 1,257 bytes in 1 blocks are still reachable in loss record 5 of 8
==10430== at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
==10430== by 0x400BBAD: UnknownInlinedFun (rtld-malloc.h:44)
==10430== by 0x400BBAD: _dl_new_object (dl-object.c:92)
==10430== by 0x4007299: _dl_map_object_from_fd (dl-load.c:1053)
==10430== by 0x4008CB7: _dl_map_object (dl-load.c:2249)
==10430== by 0x400C9CB: dl_open_worker_begin (dl-open.c:578)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430== by 0x4A49E23: dlopen_doit (dlopen.c:56)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4001678: _dl_catch_error (dl-catch.c:256)
==10430==
==10430== 2,672 bytes in 1 blocks are still reachable in loss record 6 of 8
==10430== at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
==10430== by 0x504635E: _eglFindDisplay (egldisplay.c:270)
==10430== by 0x5046A2F: _eglGetWaylandDisplay (egldisplay.c:632)
==10430== by 0x488EF6C: GetPlatformDisplayCommon (libegl.c:324)
==10430== by 0x4011B4: main (main.c:17)
==10430==
==10430== 3,720 bytes in 16 blocks are still reachable in loss record 7 of 8
==10430== at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
==10430== by 0x4013D77: UnknownInlinedFun (rtld-malloc.h:44)
==10430== by 0x4013D77: _dl_check_map_versions (dl-version.c:280)
==10430== by 0x400CA7A: dl_open_worker_begin (dl-open.c:646)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430== by 0x4A49E23: dlopen_doit (dlopen.c:56)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4001678: _dl_catch_error (dl-catch.c:256)
==10430== by 0x4A49912: _dlerror_run (dlerror.c:138)
==10430== by 0x4A49EDE: dlopen_implementation (dlopen.c:71)
==10430== by 0x4A49EDE: dlopen@@GLIBC_2.34 (dlopen.c:81)
==10430==
==10430== 20,095 bytes in 16 blocks are still reachable in loss record 8 of 8
==10430== at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
==10430== by 0x400BBAD: UnknownInlinedFun (rtld-malloc.h:44)
==10430== by 0x400BBAD: _dl_new_object (dl-object.c:92)
==10430== by 0x4007299: _dl_map_object_from_fd (dl-load.c:1053)
==10430== by 0x4008CB7: _dl_map_object (dl-load.c:2249)
==10430== by 0x400287C: openaux (dl-deps.c:64)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x4002CDF: _dl_map_object_deps (dl-deps.c:232)
==10430== by 0x400CA34: dl_open_worker_begin (dl-open.c:638)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C10F: dl_open_worker (dl-open.c:803)
==10430== by 0x4001522: _dl_catch_exception (dl-catch.c:237)
==10430== by 0x400C563: _dl_open (dl-open.c:905)
==10430==
==10430== LEAK SUMMARY:
==10430== definitely lost: 0 bytes in 0 blocks
==10430== indirectly lost: 0 bytes in 0 blocks
==10430== possibly lost: 0 bytes in 0 blocks
==10430== still reachable: 28,526 bytes in 68 blocks
==10430== suppressed: 0 bytes in 0 blocks
==10430==
==10430== For lists of detected and suppressed errors, rerun with: -s
==10430== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Я сделал что-то не так? Валгринд багги? Утечка EGL? Это непосредственно вызов в моем коде:
==10430== 2,672 bytes in 1 blocks are still reachable in loss record 6 of 8
==10430== at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
==10430== by 0x504635E: _eglFindDisplay (egldisplay.c:270)
==10430== by 0x5046A2F: _eglGetWaylandDisplay (egldisplay.c:632)
==10430== by 0x488EF6C: GetPlatformDisplayCommon (libegl.c:324)
==10430== by 0x4011B4: main (main.c:17)
Разве eglTerminate не является прямым аналогом eglGetDisplay? Я не нашел ни одного доктора, говорящего что-то другое. Я неправильно искал?
Спасибо.
На какой это ОС?





Я сделал что-то не так?
Возможно нет.
Валгринд багги?
У Valgrind есть множество проблем (и некоторые серые зоны), но это не одна из них. Я читал сотни, если не тысячи случаев бредового подтверждения, когда люди приходят к выводу, что должно быть ложное срабатывание memcheck.
Проверка утечек — одна из самых простых задач, выполняемых memcheck. Пока Valgrind удается правильно перенаправить malloc и семью, ему довольно сложно ошибиться. Классификация утечек немного сложнее: искать везде указатели на потенциальные утечки немного затруднительно.
Утечка EGL?
Valgrind показывает все еще доступную утечку памяти с помощью getaddrinfo
Косвенно, утечка происходит из динамического компоновщика. Проблема действительно в GNU libc.
Как и в ссылке выше, я рекомендую вам использовать механизм подавления для все еще доступной памяти, выделенной динамическим компоновщиком.
При этом остается вызов calloc из _eglFindDisplay (фуууу, неопределённое поведение, глобальный символ с начальным подчеркиванием). Вам нужно будет использовать исходный код EGL, чтобы выяснить, есть ли способ освободить эту память или разработчики EGL просто не удосужились ее освободить. Если вы не хотите вдаваться в подробности, вы можете снова использовать подавление.
Обновлено:
Чтобы подавить ошибки, вы можете попросить Valgrind сгенерировать подавления, используя --gen-suppresions=all. Затем скопируйте и вставьте подавление в файл и используйте его при последующих запусках (с --suppressions=[filename], который может появляться более одного раза в командной строке). Вы также можете поместить опцию --suppressions в .valgrindrc вашего домашнего каталога).
Это непроверено, но я думаю, что подавление, вероятно, должно выглядеть так
{
GNU-LIBC-DLOPEN-REACHABLE
Memcheck:Leak
match-leak-kinds: reachable
fun:*alloc
...
fun:_dl_open
}
Некоторые пояснения
calloc, так и malloc._dl_open — общая функция для всех утечекОк, очень интересно и полезно. Но я не нашел, как именно настроить фильтры valgrind, чтобы избавиться от некоторых утечек. Более того, думаете ли вы, что такие утечки glibc и EGL будут исправлены? Придется ли мне отчитываться?
Вы можете добавить свой голос на sourceware.org/bugzilla/show_bug.cgi?id=28808, но спустя более двух лет он даже не получил признания. Я ничего не знаю об EGL. Я отредактирую свой ответ, чтобы показать, как подавить.
Одна из утечек произошла из-за вызова
mainв строке 17. Но поскольку ваш второй исходный пример отредактирован, мы не знаем, что представляет собой строка 17. (т. е. какой звонок был сделан). В трассировке указаноGetPlatformDisplayCommon, но вы не вызываете это из своего источника.