0

Valgrind found the following error and I, after reading the documentation, the code and other questions in here couldn't figure it out why.

Valgrind: first warning

~$ 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: symbols

(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

Code: 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: backtrace

(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: locals

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

Extra information

  • This code is part of a library, which was ported from Solaris to Unix

What I understood:

Valgrind complains that

char ch; 

is not initialised, even after

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

After checking with GDB ch value after the above line, I have:

ch = 0 '\000'

proc_file does't correspond to that, as you can see:

(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>
}

There is no MCVE because I'm still not sure about what the problem is, I'm counting on experts to help me tackle that.

So, my question is, why is ch empty even after fread() assignment? Is this a portability issue between Solaris and Linux? Is this the problem or am I missing something?

UPDATE: File has been opened and checked for not null.

#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
Alan
  • 1,479
  • 3
  • 20
  • 36
  • 1
    What if `fread` fails? Does the message go away if you initialize `char ch=0;`? It's certainly not a portability issue. – P.P Jun 15 '15 at 11:26
  • 1
    the returned value (not the parameter value) from fread() needs to be checked to assure the fread() was successful. I.E. the returned value must be the same as the third parameter for the fread() to be successful. – user3629249 Jun 15 '15 at 11:37
  • was 'proc_file' opened? how was it opened? was the open successful? Suggest posting the code that opened the file. – user3629249 Jun 15 '15 at 11:42
  • this kind of entry: '_IO_read_ptr = 0x4352000 "debitadmin",' indicates the the loop 'while ( ! feof(proc_file) && ! ferror(proc_file))' has executed some 0x4352000 times I.E. that offset into the file. and the fread() failed so the 'ch' variable was not set – user3629249 Jun 15 '15 at 11:59
  • 1
    in general, using 'feof()' as a loop control is a bad idea. – user3629249 Jun 15 '15 at 12:05

1 Answers1

3

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

(Most probably) because fread() failed. See the detailed answer below.

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

No, there is a possible issue with your code itself, which is correctly reported by valgrind.


I cannot quite tell the below approach will solve your problem, but you should consider the below points to improve your code, e.g.,

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 2
    This should address the problem well. When fread fails to return a value, it may (or may not) set `ch` depending on the implementation. If it does not, `ch` retains its uninitialized value. Fixing the loop condition will solve the problem. – William Pursell Jun 15 '15 at 11:32