首页 > 解决方案 > 从 c 中的 popen() 创建的文件描述符读取时出现段错误

问题描述

我正在调试较少的实用程序。它通过调用 popen() 创建一个文件描述符。

fd = popen(scmd, "r");

scmd 是:

(gdb) p scmd 

$3 = 0x555555591f00 "/bin/bash -c lessecho\\ -p0x22\\ -d0x22\\ -e\\\\\\\\\\ -n0x3b\\ -n0x20\\ -n0x2a\\ -n0x3f\\ -n0x9\\ -n0xa\\ -n0x27\\ -n0x22\\ -n0x28\\ -n0x29\\ -n0x3c\\ -n0x3e\\ -n0x5b\\ -n0x5d\\ -n0x7c\\ -n0x26\\ -n0x5e\\ -n0x60\\ -n0x23\\ -n0x5c\\ -n0x24\\ -n0x25\\ -n0x3d\\ -n0x7e\\ -n0x7b\\ -n0x7d\\ -n0x2c\\ --\\ 5"

然后少调用 getc(fd) 并崩溃。我尝试在单个文件中执行此 scmd 并从 popen 中读取,它运行良好。所以我不知道为什么它崩溃得更少。

这是崩溃时的堆栈:

#0  malloc_consolidate (av=av@entry=0x7ffff7f74b80 <main_arena>) at malloc.c:4475
#1  0x00007ffff7e23e03 in _int_malloc (av=av@entry=0x7ffff7f74b80 <main_arena>, bytes=bytes@entry=4096) at malloc.c:3699
#2  0x00007ffff7e262d4 in __GI___libc_malloc (bytes=4096) at malloc.c:3058
#3  0x00007ffff7e0de84 in __GI__IO_file_doallocate (fp=0x555555591df0) at filedoalloc.c:101
#4  0x00007ffff7e1e050 in __GI__IO_doallocbuf (fp=fp@entry=0x555555591df0) at libioP.h:948
#5  0x00007ffff7e1ce24 in _IO_new_file_underflow (fp=0x555555591df0) at fileops.c:486
#6  0x00007ffff7e1e106 in __GI__IO_default_uflow (fp=0x555555591df0) at libioP.h:948
#7  0x000055555556539f in readfd (fd=0x555555591df0) at filename.c:538

这是 fd 的信息:

(gdb) p* fd
$6 = {_flags = -72539000, _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, _IO_write_base = 0x0,
  _IO_write_ptr = 0x0, _IO_write_end = 0x0, _IO_buf_base = 0x0, _IO_buf_end = 0x0, _IO_save_base = 0x0,
  _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0, _chain = 0x7ffff7f755c0 <_IO_2_1_stderr_>, _fileno = 4,
  _flags2 = 0, _old_offset = 2331849978805251629, _cur_column = 0, _vtable_offset = 48 '0', _shortbuf = "x",
  _lock = 0x555555591ee0, _offset = -1, _codecvt = 0x205c363278306e2d, _wide_data = 0xffffffffffffffff,
  _freeres_list = 0x0, _freeres_buf = 0x205c333278306e2d, __pad5 = 2331847788371930669, _mode = -1,
  _unused2 = "24\\ -n0x25\\ -n0x3d\\ "}

标签: debugginggdbpopenless-unix

解决方案


所以我不知道为什么它崩溃得更少。

目前尚不清楚less您是指GNU Less还是您编写的内容。

在任何情况下,实现内部的任何崩溃malloc(如这里发生的那样)都是堆损坏的明确指示(写入分配缓冲区的末尾,free两次 ing 某事等)。

查找此类堆损坏的标准工具是ValgrindAddress Sanitizer。任何一个都应该直接指出错误。


推荐阅读