c - fread()、solaris 到 unix 的可移植性和未初始化值的使用

标签 c linux memory stack portability

Valgrind 发现了以下错误,我在阅读文档、代码和此处的其他问题后无法弄清楚原因。

Valgrind:第一次警告

~$ valgrind --vgdb=yes --vgdb-error=0 --read-var-info=yes --leak-check=yes --track-origins=yes debitadmin*

debitadmin  ==20720== Conditional jump or move depends on uninitialised value(s)
==20720==    at 0x4013BC6: initialise (dbg.c:199)
==20720==    by 0x4013F5C: ??? (in /opt/ivb/lib/libdbg.so)
==20720==    by 0x4013917: ??? (in /opt/ivb/lib/libdbg.so)
==20720==    by 0x5F5FFE: _dl_init (in /lib/ld-2.12.so)
==20720==    by 0x5E788E: ??? (in /lib/ld-2.12.so)
==20720==  Uninitialised value was created by a stack allocation
==20720==    at 0x4013A8F: initialise (dbg.c:150)

GDB 和 Valgrind:符号

(gdb) info symbol 0x4013A8F
initialise + 5 in section .text of /opt/ivb/lib/libdbg.so

(gdb) info symbol 0x4013BC6
initialise + 316 in section .text of /opt/ivb/lib/libdbg.so

代码:dbg.c

148    void
149    initialise(void)
150    {
151        register int i = 0;
152        char buffer[FILENAME_MAX] = "";
153        char *program = NULL;
154        struct sigaction act = {0};
...
... 
195         while ( ! feof(proc_file) && ! ferror(proc_file))
196         {
197             char ch;
198             fread(&ch,1,1,proc_file);
199             if ( ch != 0 )
200             fprintf(stderr,"%c",ch);
201             else
202             fprintf(stderr," ");
203         }

GDB:回溯

(gdb) bt
#0  0x04013bc6 in initialise () at dbg.c:199
#1  0x04013f5d in __do_global_ctors_aux () from /opt/ivb/lib/libdbg.so
#2  0x04013918 in _init () from /opt/ivb/lib/libdbg.so
#3  0x005f5fff in _dl_init_internal () from /lib/ld-linux.so.2
#4  0x005e788f in _dl_start_user () from /lib/ld-linux.so.2

GDB:本地人

(gdb) info locals
ch = 0 '\000'
c = 10

额外信息

  • 此代码是从 Solaris 移植到 Unix 的库的一部分

我的理解:

Valgrind 提示说

char ch; 

没有初始化,即使在

之后
fread(&ch,1,1,proc_file);

在检查上面一行之后的 GDB ch 值后,我有:

ch = 0 '\000'

proc_file 不对应,如您所见:

(gdb) print *proc_file
$17 = {
  _flags = -72538984, 
  _IO_read_ptr = 0x4352000 "debitadmin", 
  _IO_read_end = 0x4352000 "debitadmin", 
  _IO_read_base = 0x4352000 "debitadmin", 
  _IO_write_base = 0x4352000 "debitadmin", 
  _IO_write_ptr = 0x4352000 "debitadmin", 
  _IO_write_end = 0x4352000 "debitadmin", 
  _IO_buf_base = 0x4352000 "debitadmin", 
  _IO_buf_end = 0x4353000 <Address 0x4353000 out of bounds>, 
  _IO_save_base = 0x0, 
  _IO_backup_base = 0x0, 
  _IO_save_end = 0x0, 
  _markers = 0x0, 
  _chain = 0x79c580, 
  _fileno = 3, 
  _flags2 = 0, 
  _old_offset = 0, 
  _cur_column = 0, 
  _vtable_offset = 0 '\000', 
  _shortbuf = "", 
  _lock = 0x43dc0c0, 
  _offset = -1, 
  __pad1 = 0x0, 
  __pad2 = 0x43dc0cc, 
  __pad3 = 0x0, 
  __pad4 = 0x0, 
  __pad5 = 0, 
  _mode = -1, 
  _unused2 = '\000' <repeats 39 times>
}

没有 MCVE,因为我仍然不确定问题出在哪里,我指望专家帮助我解决这个问题。

所以,我的问题是,为什么 fread() 赋值后 ch 还是空的?这是 Solaris 和 Linux 之间的可移植性问题吗?这是问题所在还是我遗漏了什么?

更新:文件已打开并检查是否为空。

#elif LINUX
    {
        char name[FILENAME_MAX];
    FILE *proc_file;
    sprintf(name,"/proc/%d/cmdline",(int)getpid());
    proc_file=fopen (name,"r");
    if ( proc_file != NULL )
    {
        int c;
        /* read in the programs name */
        for(c=0; ((fread(&buffer[c],1,1,proc_file)== 1) && (buffer[c]!=0)); c++);

        /* print out the program */
        (void)fprintf(stderr,"%s ", buffer);

        /* and the program arguments , not efficient but it works....*/
        fprintf(stderr," ");
        while ( ! feof(proc_file) && ! ferror(proc_file))
        {
            char ch;
            test *t;
            t = fread(&ch,1,1,proc_file);
            if ( ch != 0 )
            fprintf(stderr,"%c",ch);
            else
            fprintf(stderr," ");
        }
        (void) fprintf(stderr,"\n\n");
    }
    }
#endif

最佳答案

Q 1. why is ch empty even after fread() assignment?

(很可能)因为 fread() 失败了。请参阅下面的详细答案。

Q 2.Is this a portability issue between Solaris and Linux?

不,可能您的代码本身存在问题,valgrind 已正确报告该问题。


我不太确定下面的方法将解决你的问题,但你应该考虑以下几点来改进你的代码,例如,

关于c - fread()、solaris 到 unix 的可移植性和未初始化值的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30843844/

相关文章:

c - 使用 strtok 标记数字列表的程序中的错误 0Xc0000005

c - 为什么我的 timefd 上的 epoll 没有按预期工作?

linux - 快速删除多个文件之间的重复行

linux - 我如何找出 w/YUM 或 RPM 安装了哪些文件?

c - linux - 如何将编译器的所有输出捕获到文件以及需要显示输出

c++ - 尝试编写自定义 allocate_shared 分配器并使其成为 thread_local 时崩溃

c - 在二进制模式下使用 fscanf

C、Cygwin 以及编译 drand 和 srand

c - 尝试在 C 中分配二维数组时出错

android - BroadcastReceivers 和内存使用