Ошибки и утечки неинициализированного значения сборщика мусора в hboehm - PullRequest
0 голосов
/ 10 сентября 2018

Я экспериментирую с 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. Я надеюсь, что просто неправильно использую библиотеку, но я не уверен, что делаю неправильно. Любая помощь приветствуется.

1 Ответ

0 голосов
/ 10 сентября 2018

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

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

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

Читайте также руководство GC .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...