代码之家  ›  专栏  ›  技术社区  ›  Jeff M

hboehm垃圾收集器未初始化值错误和泄漏

  •  0
  • Jeff M  · 技术社区  · 6 年前

    我在试验 hboehm garbage collector ,现在只是试着 simple example . 问题是,当我用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\u gc和依赖项,构建项目,并运行valgrind。我希望我只是在某种程度上误用了图书馆,但我不确定我做错了什么。感谢您的帮助。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Basile Starynkevitch    6 年前

    你应该期待博姆的收藏家 一些 内存泄漏(因为 它是一个 总承包商 Advantages and Disadvantages of Conservative Garbage Collection 你绝对应该读。还有一个 detailed description 当然,最后是 free software

    博姆和瓦尔格林都使用类似的技术,所以他们不能很好地配合。显然,valgrind会在任何使用boehmgc的代码中检测到大量内存泄漏。在连接Boehm的GC的代码上使用valgrind是没有用的。您可以显式清除使用 GC_MALLOC .

    如果您需要一个精确的GC(特别是如果您需要更多关于GC的保证),请选择其他东西,或者编写您自己的一个(一个简单的精确标记&扫描停止世界GC很容易编写,至少在一个单线程程序中是这样;枯燥的部分是维护GC根并提供对包含指针的本地“变量”的访问。你要把它们放进 struct 在每个调用帧中,并链接这些 结构 Ravenbrook's MPS 或是我那辆旧的,没有保养的小车, Qish (也许它能激励你)。再看看 Ocaml 你应该怎么做 interface C with Ocaml .

    同时阅读 GC handbook .

    顺便说一句,你的问题是令人惊讶的:瓦尔格林(其 memcheck free 自由的 通过提供 总承包商 (替换 malloc 总承包商 -s) 是的。