Bishnu
Bishnu

Reputation: 327

Why does the following code of read() call stall?

Got no warning compiling with gcc -Wall -W -g3 <inputfile.c> but binary doesn't show anything and not getting $ prompt. gcc version 4.9.2 (Ubuntu 4.9.2-10ubuntu13). I've taken it from the book Unix System Programming by Keith Haviland. Example of read() call.

    #include<stdio.h>
    #include<stdlib.h>
    #include<fcntl.h>
    #include<unistd.h>
    #define BUFSIZE 512
    int main()
    {
    char buffer[BUFSIZE];
    int fd;
    ssize_t nread;
    long total = 0;

    if( (fd = open("fi.txt", O_RDONLY) == -1)){
        printf("error in opening file\n");
        exit(1);
        }
    while( (nread = read(fd, buffer, BUFSIZE))>0)
    total += nread;
    printf("Total characters: %ld\n", total);
    exit(0);
}

I can't understand what gdb shows. fi.txt contains only one word, Hello.

:
.
(gdb) s
13      if( (fd = open("fi.txt", O_RDONLY) == -1)){
(gdb) s
open () at ../sysdeps/unix/syscall-template.S:81
81  ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) print fd
No symbol "fd" in current context.
(gdb) s
0xb7fdbbd0 in __kernel_vsyscall ()
(gdb) s
Single stepping until exit from function __kernel_vsyscall,
which has no line number information.
main () at usp5.c:17
17      while( (nread = read(fd, buffer, BUFSIZE))>0)
(gdb) print fd
$1 = 0
(gdb) s
read () at ../sysdeps/unix/syscall-template.S:81
81  ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) s
0xb7fdbbd0 in __kernel_vsyscall ()
(gdb) s
Single stepping until exit from function __kernel_vsyscall,
which has no line number information.
s
main () at usp5.c:19
19      printf("Total characters: %ld\n", total);
(gdb) print total
$2 = 0
(gdb) print nread
$3 = 2
(gdb) s
__printf (format=0x804863d "Total characters: %ld\n") at printf.c:28
28  printf.c: No such file or directory.
(gdb) print total
No symbol "total" in current context.
(gdb) s
__x86.get_pc_thunk.bx () at ../sysdeps/i386/i686/multiarch/strcat.S:55
55  ../sysdeps/i386/i686/multiarch/strcat.S: No such file or directory.
(gdb) s
__printf (format=0x804863d "Total characters: %ld\n") at printf.c:32
32  printf.c: No such file or directory.
(gdb) s
33  in printf.c
(gdb) list
28  in printf.c
(gdb) s
_IO_vfprintf_internal (s=0xb7fb4e80 <_IO_2_1_stdout_>, format=0x804863d "Total characters: %ld\n", 
    ap=0xbfffed84 "") at vfprintf.c:222
222 vfprintf.c: No such file or directory.
(gdb) list
......

It goes on and on printing similar messages.

Upvotes: 0

Views: 420

Answers (3)

alk
alk

Reputation: 70981

[too long for a comment:]

Referring best practise debugging: If seemingly simple code fails, look for hidden unnecessarily complex but essential constructs and take them apart. In the case you show there are two such constructs:

  1. Opening the file:

      if ((fd = open("fi.txt", O_RDONLY) == -1)) 
      {
        perror("open() failed");
        ...
    

    This could be written:

      fd = open("fi.txt", O_RDONLY);
      if (fd == -1) 
      {
        perror("open() failed");
        ...
    
  2. Reading from the file:

      while ((nread = read(fd, buffer, BUFSIZE)) > 0)
    

    The could be written:

      nread = read(fd, buffer, BUFSIZE);
      while(nread > 0)      
      {
        ...
        nread = read(fd, buffer, BUFSIZE);
      }
      if (nread == -1) /* Add as much error checking as possible. */
      {
        perror("read() failed)");
      }
    

    Or more using only one call to read(), but separating error handling, for the cost of an additional if this way:

    do 
    {
      nread = read(fd, buffer, BUFSIZE);
      if (nread == -1) /* Add as much error checking as possible. */
      {
        perror("read() failed)");
      }
      else
      {
        ...
      }
    } while (nread > 0);
    

Upvotes: 0

harmic
harmic

Reputation: 30597

You have misplaced brackets here:

if( (fd = open("fi.txt", O_RDONLY) == -1)){

which results in fd being set to 0, rather than the return value of open. Thus you are actually reading from fd 0 (STDIN).

It should be:

if( (fd = open("fi.txt", O_RDONLY)) == -1){

Upvotes: 3

Spark.Bao
Spark.Bao

Reputation: 5763

I think you just make a low level mistake:

change this line code:

if( (fd = open("fi.txt", O_RDONLY) == -1)){

to

if( (fd = open("fi.txt", O_RDONLY)) == -1){

then you will get correct result.

because your code will make fd = 0, and 0 is the stdin, so the progrm always wait your input.

Upvotes: 1

Related Questions