"Segmentation fault (core dumped)" for: "No such file or directory" for libioP.h, printf-parse.h, vfprintf-internal.c, 等等

"Segmentation fault (core dumped)" for: "No such file or directory" for libioP.h, printf-parse.h, vfprintf-internal.c, etc

核心转储文件中的示例错误:

1289    vfprintf-internal.c: No such file or directory.
111 printf-parse.h: No such file or directory.
948 libioP.h: No such file or directory.
948 libioP.h: No such file or directory.

我正在研究 fast_malloc() 实现,但是在我用自己的实现覆盖 malloc()free() 之后,由于未知原因出现分段错误,但在此之前不会(意思是,如果我调用 fast_malloc() 没问题,但如果我希望能够调用 malloc() 来获取我的实现,它似乎被破坏了)。

为什么会出现段错误?

示例输出,在可以打印任何内容之前,包括 main() 开头的打印语句,以及我的 fast_malloc():

中的一些调试打印
Segmentation fault (core dumped)

我已经打开核心转储 as I explain here

因此,gdb path/to/my/executable core 显示了以下一些 core 文件信息。请注意,每个 运行 可能会导致“没有这样的文件或目录”中缺少的文件的不同声明。

  1. 一个运行:
Reading symbols from build/fast_malloc_unit_tests...

warning: core file may not match specified executable file.
[New LWP 1257155]
Core was generated by `build/fast_malloc_unit_tests'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fd50fc7ba01 in __vfprintf_internal (s=0x7fd50fdee6a0 <_IO_2_1_stdout_>, 
    format=0x5622fd1b8010 "DEBUG: %s():\n", ap=ap@entry=0x7ffec28300a0, 
    mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1289
1289    vfprintf-internal.c: No such file or directory.
(gdb) bt
#0  0x00007fd50fc7ba01 in __vfprintf_internal (s=0x7fd50fdee6a0 <_IO_2_1_stdout_>, 
    format=0x5622fd1b8010 "DEBUG: %s():\n", ap=ap@entry=0x7ffec28300a0, 
    mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1289
#1  0x00007fd50fc66ebf in __printf (format=<optimized out>) at printf.c:33
#2  0x00005622fd1b53eb in fast_malloc (num_bytes=1024) at src/fast_malloc.c:225
#3  0x00005622fd1b5b66 in malloc (num_bytes=1024) at src/fast_malloc.c:496
#4  0x00007fd50fc86e84 in __GI__IO_file_doallocate (fp=0x7fd50fdee6a0 <_IO_2_1_stdout_>)
    at filedoalloc.c:101
#5  0x00007fd50fc97050 in __GI__IO_doallocbuf (fp=fp@entry=0x7fd50fdee6a0 <_IO_2_1_stdout_>)
    at libioP.h:948
#6  0x00007fd50fc960b0 in _IO_new_file_overflow (f=0x7fd50fdee6a0 <_IO_2_1_stdout_>, ch=-1)
    at fileops.c:745
#7  0x00007fd50fc94835 in _IO_new_file_xsputn (n=7, data=<optimized out>, f=<optimized out>)
    at libioP.h:948
#8  _IO_new_file_xsputn (f=0x7fd50fdee6a0 <_IO_2_1_stdout_>, data=<optimized out>, n=7)
    at fileops.c:1197
#9  0x00007fd50fc7baf2 in __vfprintf_internal (s=0x7fd50fdee6a0 <_IO_2_1_stdout_>, 
    format=0x5622fd1b8010 "DEBUG: %s():\n", ap=ap@entry=0x7ffec28308e0, 
    mode_flags=mode_flags@entry=0) at ../libio/libioP.h:948
#10 0x00007fd50fc66ebf in __printf (format=<optimized out>) at printf.c:33
#11 0x00005622fd1b53eb in fast_malloc (num_bytes=1024) at src/fast_malloc.c:225
#12 0x00005622fd1b5b66 in malloc (num_bytes=1024) at src/fast_malloc.c:496
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) q

  1. 另一个:
Reading symbols from build/fast_malloc_unit_tests...

warning: core file may not match specified executable file.
[New LWP 1257787]
Core was generated by `build/fast_malloc_unit_tests'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f20b0bbba80 in __find_specmb (
    format=0x5644c516d108 "DEBUG:   block_map_i = %zu (num_bytes requested to allocate = %zu; smallest user block size large enough = %zu)\n") at printf-parse.h:111
111 printf-parse.h: No such file or directory.
(gdb) bt
#0  0x00007f20b0bbba80 in __find_specmb (
    format=0x5644c516d108 "DEBUG:   block_map_i = %zu (num_bytes requested to allocate = %zu; smallest user block size large enough = %zu)\n") at printf-parse.h:111
#1  __vfprintf_internal (s=0x7f20b0d2e6a0 <_IO_2_1_stdout_>, 
    format=0x5644c516d108 "DEBUG:   block_map_i = %zu (num_bytes requested to allocate = %zu; smallest user block size large enough = %zu)\n", ap=ap@entry=0x7ffe7f6ea580, mode_flags=mode_flags@entry=0)
    at vfprintf-internal.c:1365
#2  0x00007f20b0ba6ebf in __printf (format=<optimized out>) at printf.c:33
#3  0x00005644c516a47d in fast_malloc (num_bytes=1024) at src/fast_malloc.c:244
#4  0x00005644c516ab4e in malloc (num_bytes=1024) at src/fast_malloc.c:496
#5  0x00007f20b0bc6e84 in __GI__IO_file_doallocate (fp=0x7f20b0d2e6a0 <_IO_2_1_stdout_>)
    at filedoalloc.c:101
#6  0x00007f20b0bd7050 in __GI__IO_doallocbuf (fp=fp@entry=0x7f20b0d2e6a0 <_IO_2_1_stdout_>)
    at libioP.h:948
#7  0x00007f20b0bd60b0 in _IO_new_file_overflow (f=0x7f20b0d2e6a0 <_IO_2_1_stdout_>, ch=-1)
    at fileops.c:745
#8  0x00007f20b0bd4835 in _IO_new_file_xsputn (n=23, data=<optimized out>, f=<optimized out>)
    at libioP.h:948
#9  _IO_new_file_xsputn (f=0x7f20b0d2e6a0 <_IO_2_1_stdout_>, data=<optimized out>, n=23)
    at fileops.c:1197
#10 0x00007f20b0bbbaf2 in __vfprintf_internal (s=0x7f20b0d2e6a0 <_IO_2_1_stdout_>, 
    format=0x5644c516d108 "DEBUG:   block_map_i = %zu (num_bytes requested to allocate = %zu; smallest--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) q

  1. 另一个:
Reading symbols from build/fast_malloc_unit_tests...

warning: core file may not match specified executable file.
[New LWP 1258037]
Core was generated by `build/fast_malloc_unit_tests'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f901ef65e4d in __GI__IO_file_doallocate (fp=0x7f901f0cd6a0 <_IO_2_1_stdout_>)
    at libioP.h:948
948 libioP.h: No such file or directory.
(gdb) q
  1. 另一个
Reading symbols from build/fast_malloc_unit_tests...

warning: core file may not match specified executable file.
[New LWP 1258336]
Core was generated by `build/fast_malloc_unit_tests'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f5e4b551a80 in __find_specmb (
    format=0x562fac6d7108 "DEBUG:   block_map_i = %zu (num_bytes requested to allocate = %zu; smallest user block size large enough = %zu)\n") at printf-parse.h:111
111 printf-parse.h: No such file or directory.
(gdb) q

我目前的 gcc 构建选项:

-Wall -Wextra -Werror -O0 -ggdb -std=c11 -save-temps=obj -DDEBUG

可能与我拥有的这个 DEBUG_PRINTF() 宏有关,我在 fast_malloc().

中调用它
#ifdef DEBUG
    /// Debug printf function.
    /// See: 
    #define DEBUG_PRINTF(...) printf("DEBUG: "__VA_ARGS__)
#else
    #define DEBUG_PRINTF(...) \
        do                    \
        {                     \
        } while (0)
#endif

为什么 malloc() 在程序启动之前就被调用了?我不在任何地方称它为 。但是,请注意,您可以看到 malloc() 被调用 1024 字节,如在 运行s 1 和 2 的堆栈跟踪中可见(尽管它发生在每个 运行,这些是我粘贴的足够你可以看到它)。

我的 malloc()free() 覆盖看起来像这样:

inline void* malloc(size_t num_bytes)
{
    return fast_malloc(num_bytes);
}

inline void free(void* ptr)
{
    fast_free(ptr);
}

我的单线程程序 malloc() 被神秘地调用了,而我在启动时以某种方式调用它是多线程的吗?是否发生了一些奇怪的程序初始化事情?我的 fast_malloc() 实现目前不是线程安全的,所以如果 Linux 在某种程序初始化或其他过程中进行一些奇怪的多线程 malloc() 调用,那可能是损坏的原因,因为同样,覆盖 malloc()fast_malloc() 还不是线程安全的。

好像和里面打印malloc()有关。 malloc() 里面禁止打印吗?

这是来自核心转储的最近堆栈跟踪的底部(第一次调用在最底部):

#127471 0x00005626d43dca28 in malloc (num_bytes=1024) at src/fast_malloc.c:494
#127472 0x00007faa222a7e84 in __GI__IO_file_doallocate (fp=0x7faa2240f6a0 <_IO_2_1_stdout_>) at filedoalloc.c:101
#127473 0x00007faa222b8050 in __GI__IO_doallocbuf (fp=fp@entry=0x7faa2240f6a0 <_IO_2_1_stdout_>) at libioP.h:948
#127474 0x00007faa222b70b0 in _IO_new_file_overflow (f=0x7faa2240f6a0 <_IO_2_1_stdout_>, ch=-1) at fileops.c:745
#127475 0x00007faa222b5835 in _IO_new_file_xsputn (n=13, data=<optimized out>, f=<optimized out>) at libioP.h:948
#127476 _IO_new_file_xsputn (f=0x7faa2240f6a0 <_IO_2_1_stdout_>, data=<optimized out>, n=13) at fileops.c:1197
#127477 0x00007faa222aa678 in __GI__IO_puts (str=0x5626d43df227 '=' <repeats 13 times>) at libioP.h:948
#127478 0x00005626d43dca28 in malloc (num_bytes=1024) at src/fast_malloc.c:494
#127479 0x00007faa222a7e84 in __GI__IO_file_doallocate (fp=0x7faa2240f6a0 <_IO_2_1_stdout_>) at filedoalloc.c:101
#127480 0x00007faa222b8050 in __GI__IO_doallocbuf (fp=fp@entry=0x7faa2240f6a0 <_IO_2_1_stdout_>) at libioP.h:948
#127481 0x00007faa222b70b0 in _IO_new_file_overflow (f=0x7faa2240f6a0 <_IO_2_1_stdout_>, ch=-1) at fileops.c:745
#127482 0x00007faa222b5835 in _IO_new_file_xsputn (n=13, data=<optimized out>, f=<optimized out>) at libioP.h:948
#127483 _IO_new_file_xsputn (f=0x7faa2240f6a0 <_IO_2_1_stdout_>, data=<optimized out>, n=13) at fileops.c:1197
#127484 0x00007faa222aa678 in __GI__IO_puts (str=0x5626d43df227 '=' <repeats 13 times>) at libioP.h:948
#127485 0x00005626d43dca28 in malloc (num_bytes=1024) at src/fast_malloc.c:494
#127486 0x00007faa222a7e84 in __GI__IO_file_doallocate (fp=0x7faa2240f6a0 <_IO_2_1_stdout_>) at filedoalloc.c:101
#127487 0x00007faa222b8050 in __GI__IO_doallocbuf (fp=fp@entry=0x7faa2240f6a0 <_IO_2_1_stdout_>) at libioP.h:948
#127488 0x00007faa222b70b0 in _IO_new_file_overflow (f=0x7faa2240f6a0 <_IO_2_1_stdout_>, ch=-1) at fileops.c:745
#127489 0x00007faa222b5835 in _IO_new_file_xsputn (n=49, data=<optimized out>, f=<optimized out>) at libioP.h:948
#127490 _IO_new_file_xsputn (f=0x7faa2240f6a0 <_IO_2_1_stdout_>, data=<optimized out>, n=49) at fileops.c:1197
#127491 0x00007faa222aa678 in __GI__IO_puts (str=0x5626d43df238 "Running UNIT tests for the \"fast_malloc\" module.\n") at libioP.h:948
#127492 0x00005626d43dca98 in main () at src/fast_malloc_unit_tests.c:35
(gdb) 

什么是 __GI__IO_puts_IO_new_file_xsputn 以及您向上移动时的其他函数调用?他们在其他线程中调用吗?他们是在幕后调用 malloc() 吗?看来 __GI__IO_file_doallocate 是...

您正在 malloc 实施中调用 printf。那不会有好下场的。

在堆栈跟踪中,您可以清楚地看到 printf 本身 调用 malloc.

如果您的 malloc 在操作其数据结构的过程中不准备被调用,它将崩溃(可能就是这里发生的情况)。

或者,您也可以无限递归结束,当 malloc 调用 printf 时,调用 malloc,调用 printf,等等

TL;DR:当实现像 malloc 这样低级的东西时,你 必须 坚持使用本身不分配任何东西的低级函数,或者直接系统调用。

Why is malloc() getting called before the program starts anyway?

因为低级功能,例如动态加载器需要在自己初始化时分配内存。

您的 malloc 必须 在进程生命周期的早期工作;很久以前 main.

Is printing inside malloc() forbidden?

禁止所有可能分配内存的东西

在实践中,您只需要调用异步信号安全例程,因为非异步信号安全例程可能分配,如果不是现在那么将来。

跟进并回答我自己的问题: 似乎是正确的。

更具体地说:我有两个主要问题:

  1. malloc()printf() 之间的无限递归。
  2. 通过释放和重新使用系统认为它具有独占访问权限的内存来破坏数据。

第一题:无限递归

我调用 printf() 在我的 fast_malloc() 实现中做一些调试打印。只要我不使用我的 fast_malloc() 覆盖 malloc(),就可以了(只要我用互斥量保护打印以使其多线程安全)。但是,一旦我用我的 fast_malloc() 覆盖 malloc(),这就不行了,因为 printf() 调用 malloc() 来创建一个缓冲区,它可以在其中放置格式化的字符串数据。因此,一旦 malloc() fast_malloc() 覆盖 ,我们将以无限递归结束:在 main() 甚至 运行 之前,系统调用 malloc() 准备一些东西。这会调用 printf(),它会调用 malloc(),它会调用 printf()...一直到堆栈溢出...都在它进入我的 main() 函数之前。

因此,我看到我的照片为零,而且 main() 甚至没有输入。您可以从我在回答中发布的最后一个堆栈跟踪中看到,崩溃时我的堆栈上有 127492 堆栈帧……此时堆栈溢出。完整性检查:对于 a stack size of ~7.4 MB,这相当于每个堆栈帧大约 7400000/127492 = ~58 字节,这似乎是合理的。

第二个问题:我正在释放并重用系统 (glibc) 认为它已安全获取并仍在控制的内存

我 运行ning 的代码是我的 fast_malloc_unit_tests.c 程序,除其他外,它会多次重新初始化我在后台使用的内存池。每次执行此操作时,它都会考虑释放之前分配的内存,并在需要时重新分配它。但是,printf() 和其他系统调用 运行 在 main() 之前甚至被输入时已经调用了 malloc() 并且认为它们仍然拥有这个内存。所以,我们最终错误地重用了他们正在使用的内存,导致数据损坏和崩溃。

在我的 malloc() 实现中禁用所有打印后,从而消除了无限递归问题,我能够看到此行为。在这种情况下,代码 did 进入我的 main() 功能,我 did 在崩溃前看到了我的几十个打印件,并且在崩溃时我的堆栈上只有 2 个调用(堆栈帧)(而不是 127492 帧)。他们是:

#0  0x000055555555589d in fast_malloc_print_stats () at src/fast_malloc.c:464
#1  0x0000555555556228 in main () at src/fast_malloc_unit_tests.c:129

完整输出:

Program received signal SIGSEGV, Segmentation fault.
0x000055555555589d in fast_malloc_print_stats () at src/fast_malloc.c:464
464             block = block->next_free_block;
(gdb) bt
#0  0x000055555555589d in fast_malloc_print_stats () at src/fast_malloc.c:464
#1  0x0000555555556228 in main () at src/fast_malloc_unit_tests.c:129

其中 fast_malloc.c 第 464 行包含:

while (block != NULL)
{
    free_block_cnt_walked++;
    block = block->next_free_block;   <==== line 464
}

据我所知没有任何问题,因为它是一个简单的副本并且 block 已经保证不是 NULL,所以调用 block->next_free_block 不能可能正在取消引用 NULL ptr。因此,我认为 分段错误 一定是由于内存损坏造成的,因为该内存被双重使用,因此 block ptr 可能是一个超出有效范围的损坏地址供我们阅读——因此出现段错误。


就是这样(我想)。现在我必须去做适当的修复并继续研究这个问题。非常感谢

另请参阅:

  1. [我的回答:从不调用malloc()safe_printf()函数,从而解决无限递归问题!]