fread()、solaris 到 unix 的可移植性和未初始化值的使用
fread(), solaris to unix portability and use of uninitialised values
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 '[=14=]0'
c = 10
额外信息
- 此代码是从 Solaris 移植到 Unix 的库的一部分
我的理解:
Valgrind 抱怨
char ch;
未初始化,即使在
之后
fread(&ch,1,1,proc_file);
在用 GDB ch
值检查上面一行后的值后,我有:
ch = 0 '[=17=]0'
proc_file 不对应,如您所见:
(gdb) print *proc_file
= {
_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 '[=18=]0',
_shortbuf = "",
_lock = 0x43dc0c0,
_offset = -1,
__pad1 = 0x0,
__pad2 = 0x43dc0cc,
__pad3 = 0x0,
__pad4 = 0x0,
__pad5 = 0,
_mode = -1,
_unused2 = '[=18=]0' <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 已正确报告。
我不能完全确定以下方法是否会解决您的问题,但您应该考虑以下几点来改进您的代码,例如,
第 1 点: 检查 fread()
to ensure sucess. If fread()
is failure, using ch
later will invoke read-before-write scenario. As ch
is automatic local variable and not initialized explicitly, it will invoke undefined behaviour 的 return 值。
第 2 点: 阅读:Why is while ( !feof (file) )
(almost) always wrong?
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 '[=14=]0'
c = 10
额外信息
- 此代码是从 Solaris 移植到 Unix 的库的一部分
我的理解:
Valgrind 抱怨
char ch;
未初始化,即使在
之后fread(&ch,1,1,proc_file);
在用 GDB ch
值检查上面一行后的值后,我有:
ch = 0 '[=17=]0'
proc_file 不对应,如您所见:
(gdb) print *proc_file
= {
_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 '[=18=]0',
_shortbuf = "",
_lock = 0x43dc0c0,
_offset = -1,
__pad1 = 0x0,
__pad2 = 0x43dc0cc,
__pad3 = 0x0,
__pad4 = 0x0,
__pad5 = 0,
_mode = -1,
_unused2 = '[=18=]0' <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 已正确报告。
我不能完全确定以下方法是否会解决您的问题,但您应该考虑以下几点来改进您的代码,例如,
第 1 点: 检查
fread()
to ensure sucess. Iffread()
is failure, usingch
later will invoke read-before-write scenario. Asch
is automatic local variable and not initialized explicitly, it will invoke undefined behaviour 的 return 值。第 2 点: 阅读:Why is
while ( !feof (file) )
(almost) always wrong?