Утечка памяти EGL

Мне сказали, что 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? Я не нашел ни одного доктора, говорящего что-то другое. Я неправильно искал?

Спасибо.

Одна из утечек произошла из-за вызова main в строке 17. Но поскольку ваш второй исходный пример отредактирован, мы не знаем, что представляет собой строка 17. (т. е. какой звонок был сделан). В трассировке указано GetPlatformDisplayCommon, но вы не вызываете это из своего источника.

Craig Estey 24.05.2024 02:39

На какой это ОС?

Paul Floyd 24.05.2024 07:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я сделал что-то не так?

Возможно нет.

Валгринд багги?

У 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 будут исправлены? Придется ли мне отчитываться?

Lewis Anesa 25.05.2024 00:10

Вы можете добавить свой голос на sourceware.org/bugzilla/show_bug.cgi?id=28808, но спустя более двух лет он даже не получил признания. Я ничего не знаю об EGL. Я отредактирую свой ответ, чтобы показать, как подавить.

Paul Floyd 25.05.2024 07:29

Другие вопросы по теме