LibGit2 初始化的内存问题

Memory problems with LibGit2 initialization

当我初始化并关闭 LibGit2 时,我留下了可访问内存 and/or 错误。

我的测试系统是 Ubuntu 18.04,libgit2 0.26,其中 g++ -v 给我 gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) 和一个 FreeBSD 11.3 VM,libgit 0.28.3,不幸的是,我无法复制& 粘贴自。这里 g++ -v 给出 gcc version 9.2.0 (FreeBSD Ports Collection.

这是一个最小的例子:

#include <git2.h>
int main () {
    git_libgit2_init();
    git_libgit2_shutdown();
    return 0;
}

关于 Ubuntu 我 运行 以下内容:

➜  libelektra git:(libgit_test) ✗ g++ minimal.c -lgit2 && valgrind ./a.out
==1174== Memcheck, a memory error detector
==1174== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1174== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1174== Command: ./a.out
==1174== 
==1174== 
==1174== HEAP SUMMARY:
==1174==     in use at exit: 192 bytes in 12 blocks
==1174==   total heap usage: 1,354 allocs, 1,342 frees, 107,044 bytes allocated
==1174== 
==1174== LEAK SUMMARY:
==1174==    definitely lost: 0 bytes in 0 blocks
==1174==    indirectly lost: 0 bytes in 0 blocks
==1174==      possibly lost: 0 bytes in 0 blocks
==1174==    still reachable: 192 bytes in 12 blocks
==1174==         suppressed: 0 bytes in 0 blocks
==1174== Rerun with --leak-check=full to see details of leaked memory
==1174== 
==1174== For counts of detected and suppressed errors, rerun with: -v
==1174== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

very first example from the documentationgit_libgit2_shutdown(); 应该清理所有内容时,为什么我有可用的内存?

虽然 Valgrind 文档说 some reachable memory might be ok,但在 FreeBSD 上事情变得非常疯狂。我有一些虚拟机的截图 One Two Three。 我怎样才能避免这种情况?

关于不同内存处理的补充说明。我的目标是使用 git_merge_file 函数 in this project。它应该看起来像这样:

#include <git2.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main () {
    git_libgit2_init();
    sleep (1);
    git_merge_file_result out = { 0 }; // out.ptr will not receive a terminating null character
    git_merge_file_input libgit_base;
    git_merge_file_input libgit_our;
    git_merge_file_input libgit_their;
    git_merge_file_init_input(&libgit_base, GIT_MERGE_FILE_INPUT_VERSION);
    git_merge_file_init_input(&libgit_our, GIT_MERGE_FILE_INPUT_VERSION);
    git_merge_file_init_input(&libgit_their, GIT_MERGE_FILE_INPUT_VERSION);
    libgit_base.ptr = "A";
    libgit_base.size = strlen("A");
    libgit_our.ptr = "A";
    libgit_our.size = strlen("A");
    libgit_their.ptr = "A";
    libgit_their.size = strlen("A");
    int exitCode = git_merge_file (&out, &libgit_base, &libgit_our, &libgit_their, 0);
    printf("Code is %d\n", exitCode);
    git_merge_file_result_free (&out);
    git_libgit2_shutdown();
    sleep (1);
    return 0;
}

当我删除初始化 and/or 关闭时,我有时会在 Ubuntu 上获得 0 个仍可访问的内存,但在 FreeBSD 上会出现分段错误。是否值得仔细研究一下,或者忽略 that LibGit must be initialized?

时这种行为差异是否正常?

在 BSD VM 的屏幕截图中,__pthread_once 是问题的根源。这和 __pthread_once_slow 似乎与所有错误有关:开头的 Ubuntu 上的 192 个字节,BSD 和 Ubuntu 底部的更高级示例以及我的实际应用程序。

据我所知,您的代码或 Valgrind 报告本身没有任何问题,正如您 pointed out:

"still reachable" means your program is probably ok -- it didn't free some memory it could have. This is quite common and often reasonable. Don't use --show-reachable=yes if you don't want to see these reports.

因此,这 192 个字节很可能并没有真正泄漏,您只是在 OS 决定夺回该内存块之前设法退出程序 — 即。它将该块保留在进程的权限范围内,作为对下一次分配的优化。在这种情况下,进程刚刚退出,因此必须在进程终止时回收内存,我认为这就是 "still reachable" 的意思——内存很好,将被正常回收。希望.

FreeBSD 上的 Valgrind 错误不是分配问题,而是使用未初始化的内存区域。在解析证书(?)时,它们看起来不在 libgit2 内部,而是 OpenSSL 本身。您可以找到从 here.

开始的底层 OpenSSL 初始化

Is it worth giving this a closer look or is such a difference in behavior normal when ignoring the that LibGit must be initialized?

我很想说不,是的。代码现在正在生成包含 随机垃圾 而不是堆栈分配的 pthread_something 的内存位置。段错误必然会随机发生。

HTH!