Сборщик мусора hboehm, ошибки и утечки неинициализированных значений

Я экспериментирую с сборщик мусора hboehm, а пока просто пытаюсь запустить их простой пример. Проблема в том, что когда я проверяю результат с помощью Valgrind, я получаю много ошибок «Использование неинициализированного значения» и, как ни странно, утечки памяти.

Полный проект минимального примера, воспроизводящего проблему.

cmake_minimum_required(VERSION 3.10)

# This "outer" CMake file works as a dependency fetcher, and it consists almost exclusively of ExternalProject commands.
# The "inner" CMake file under project/ is a more traditional CMake file. It uses the find_* commands to locate
# dependencies without any knowledge or assumptions about where those dependencies live or how they got there.

include(ExternalProject)

ExternalProject_Add(
    libatomic_ops
    URL http://www.hboehm.info/gc/gc_source/libatomic_ops-7.6.2.tar.gz
    CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND ""
)
ExternalProject_Get_Property(libatomic_ops SOURCE_DIR)
set(libatomic_ops_SOURCE_DIR "${SOURCE_DIR}")

ExternalProject_Add(
    hboehm_gc
    URL http://www.hboehm.info/gc/gc_source/gc-7.6.4.tar.gz
    DEPENDS libatomic_ops
    BUILD_IN_SOURCE TRUE
    # hboehm_gc requires libatomic_ops be placed in a libatomic_ops subdirectory
    PATCH_COMMAND "${CMAKE_COMMAND}" -E copy_directory "${libatomic_ops_SOURCE_DIR}" "<SOURCE_DIR>/libatomic_ops"
    CONFIGURE_COMMAND ./configure "--prefix=<INSTALL_DIR>"
    BUILD_COMMAND make
    INSTALL_COMMAND make install
)
ExternalProject_Get_Property(hboehm_gc INSTALL_DIR)
set(hboehm_gc_INSTALL_DIR "${INSTALL_DIR}")

# Now that we have our dependencies on disk to be found, it's safe to configure (run cmake on) the real project
ExternalProject_Add(
    main DEPENDS hboehm_gc
    DOWNLOAD_COMMAND ""
    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/project"
    BUILD_ALWAYS TRUE
    CMAKE_ARGS "-DCMAKE_PREFIX_PATH=${hboehm_gc_INSTALL_DIR}"
    INSTALL_COMMAND ""
    TEST_COMMAND "${CMAKE_CTEST_COMMAND}" --verbose
)

cmake_minimum_required(VERSION 3.10)

find_path(HBOEHM_GC_INSTALL_DIR include/gc.h)
find_program(VALGRIND_COMMAND valgrind)

add_executable(main src/main.cpp)
target_compile_features(main PRIVATE cxx_std_14)
target_link_libraries(main PRIVATE "${HBOEHM_GC_INSTALL_DIR}/lib/libgc.a" pthread)
target_include_directories(main PRIVATE "${HBOEHM_GC_INSTALL_DIR}/include")

enable_testing()
add_test(NAME valgrind COMMAND "${VALGRIND_COMMAND}" "$<TARGET_FILE:main>")
set_tests_properties(
    valgrind PROPERTIES
    PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors from 0 contexts"
)

#include <cassert>
#include <iostream>
#include <gc.h>

int main() {
  int i;

  GC_INIT();    /* Optional on Linux/X86; see below.  */
  for (i = 0; i < 10000000; ++i)
   {
     int **p = (int **) GC_MALLOC(sizeof(int *));
     int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
     assert(*p == 0);
     *p = (int *) GC_REALLOC(q, 2 * sizeof(int));
     if (i % 100000 == 0)
       std::cout << "Heap size = " << GC_get_heap_size() << "\n";
   }
  return 0;
}

Просто нужно:

mkdir build
cd build
cmake ..
make

Он загрузит hboehm_gc и зависимости, соберет проект и запустит valgrind. Я надеюсь, что просто неправильно использую библиотеку, но я не уверен, что делаю не так. Любая помощь приветствуется.

Было бы неплохо объяснить, почему вы экспериментируете с GC и какое приложение, использующее этот GC, вы имеете в виду ...

Basile Starynkevitch 10.09.2018 08:43

Без большего контекста и мотивации (о которых я просил) ваш вопрос неясен.

Basile Starynkevitch 10.09.2018 19:28
0
2
111
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы должны ожидать, что у сборщика Боэма будут утечки памяти некоторые (потому что это сборщик мусора консервативный). Поскольку Boehm GC является консервативным сборщиком мусора, он не дает (и не может) дать надежных гарантий. Но вы надеетесь, что в нем не будет слишком много утечек или потерь памяти (в некоторых документах упоминается 20% утечка, что типично для GC Boehm в Linux / x86-64). В GC Boehm есть страница о Преимущества и недостатки консервативной сборки мусора, которую вы обязательно должны прочитать. И еще есть его Подробное описание, и, наконец, это бесплатно программное обеспечение, так что вы можете (и, возможно, должны) изучить его исходный код.

И Boehm, и valgrind используют схожие технологии, поэтому они не могут хорошо играть вместе. Очевидно, valgrind обнаружит множество утечек памяти в любом коде, использующем Boehm GC. Использование valgrind в коде, связывающем сборщик мусора Бема, бесполезно. Вы можете явно очистить каждую зону памяти, полученную с помощью GC_MALLOC.

Если вам нужен точный сборщик мусора (в частности, если вам нужно больше гарантий относительно сборщика мусора), выберите что-то другое или закодируйте свой собственный (сборщик мусора с наивной точной меткой и разверткой легко закодировать, по крайней мере, в однопоточном программа; скучная часть состоит в том, чтобы поддерживать корни GC и предоставлять доступ к вашим локальным "переменным", содержащим указатели. Вы поместите их в некоторый struct в каждый кадр вызова и свяжете эти struct-ы вместе). Может быть, загляните в MPS Рэйвенбрука или мой старый, не обслуживаемый и глючный, Киш (возможно, это могло бы вас вдохновить). Посмотрите также на Ocaml GC и как вы должны интерфейс C с Ocaml.

Прочтите также Справочник по ГХ.

Кстати, ваш вопрос удивителен: valgrind (его инструмент memcheck) предназначен для поиска отсутствующих free-ов, и весь смысл Boehm GC состоит в том, чтобы сделать free «бесполезным», предоставив GC_MALLOC (замена malloc), который не нуждается в каком-либо виде освобождения операции (поэтому нет смысла использовать valgrind в программе, которая выполняет GC_MALLOC-s).

Если Boehm и valgrind плохо сочетаются друг с другом, есть ли другой способ узнать скорость утечки и проверить другие проблемы с памятью?

Jeff M 10.09.2018 08:06

Возможно нет. Вы можете использовать только API GC от Boehm. И если вы используете GC Бема, вы соглашаетесь с тем, что он консервативен и что у вас будут утечки. И я не понимаю, почему вы хотите знать скорость утечки? Пожалуйста, отредактируйте свой вопрос, чтобы объяснить больше

Basile Starynkevitch 10.09.2018 08:07

По сути, если вы хотите измерить скорость утечки, вам необходимо реализовать свой собственный точный GC в дополнение к использованию Boehm, чтобы ваш точный GC вычислял совокупный размер и количество живых объектов и сравнивал это с тем, что потребляет GC Boehm. Это того стоит? Наверное, нет ... (если вы не пишете статью для сравнения сборщиков мусора)

Basile Starynkevitch 10.09.2018 08:30

Просто для моего душевного спокойствия. Мне нравится иметь возможность убедиться, что все работает, как ожидалось. Если я не могу использовать valgrind, то, полагаю, мне нужно просто предположить, по большей части, что hboehm работает так, как рекламируется?

Jeff M 10.09.2018 19:18

Сборщик мусора Бема объявляется как сборщик мусора консервативный. Нет никаких обещаний избежать «утечек». Он работает эвристически, поэтому иногда плохо. Похоже, вы слишком многого ожидаете от Boehm GC (который на практике большую часть времени работает довольно хорошо). Не может и не дает гарантий!

Basile Starynkevitch 10.09.2018 19:19

До сих пор не понимаю, какое приложение вы имеете в виду. Пожалуйста, редактировать ваш вопрос, чтобы улучшить его? Что будет, если «потеряно» 30% памяти? Во многих случаях вам все равно. Но я не могу прочесть в ваших мыслях и угадать, какое приложение вы кодируете.

Basile Starynkevitch 10.09.2018 19:22

Мой вопрос как заданный то, что я хотел спросить. Я хотел знать, почему valgrind сообщает об ошибках, и, похоже, ответ такой: «Бем и valgrind плохо сочетаются друг с другом». Все мои комментарии после этого были продолжением обсуждения.

Jeff M 10.09.2018 20:12

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