0

I wrote the following code in GDB online debugger :

#include <stdio.h>

int main()
{
  printf("jkjkkjkj");

  int p , n;
  FILE *fp;
  printf("jkjkkjkj2");
  fp = fopen("abc.txt","r");

  while ( (n = getc(fp))!= EOF)
  {
    printf( "the chareacter here is %d \n", n);
  }

  n = fclose(fp);
  return 0;
}

While executing the code I am getting a segmentation fault at the line where I am trying to fetch the characters from the file. I know that as the file does not exist the segmentation fault error is coming.

However, what intrigues me is the absence of the messages that I am trying to print on the screen. I tried checking on debugger and once I found:

optimized out written near the line no

However, I tried putting getchar() here and there, the messages got printed on the screen even if the segmentation fault persists.

How to explain this? Why is this happening? Why are the messages printed when I am putting getchar() at different places?

I had tried writing this code on a Solaris server and compiling using GCC. The code got compiled but I did not get any output message even when a file with the name provided in the directory existed.

alk
  • 69,737
  • 10
  • 105
  • 255
  • 5
    Regarding the `printf` debugging, you forget that output to `stdout` by default is *line buffered*. Output is buffered until there is a newline. So I suggest you make a habit of always printing a newline at the end of your strings (like `printf("jkjkkjkj\n");`). Output is also flushed when you want to read from `stdin`, those two streams are connected. – Some programmer dude May 05 '18 at 11:38
  • You should have seen the messages when it prints the first `the character here is` line, since that has a newline in it. – Barmar May 05 '18 at 11:41
  • @Someprogrammerdude : Thanks a lot , that worked – Kanishk Viman May 05 '18 at 11:43
  • Print error/debug logging output to the unbuffered Standard Error Output: `fprintf(stderr, "%d", 42);` or `fputs("bla", stderr);` – alk May 05 '18 at 11:43
  • @Barmar : I cannot because there is segmentation fault at the line when it is trying to read characters just before that printf – Kanishk Viman May 05 '18 at 11:44
  • @alk : Will try that too thanks – Kanishk Viman May 05 '18 at 11:45
  • @KanishkViman I meant when you run it on your Solaris system and the file exists. – Barmar May 05 '18 at 11:47
  • 1
    @Barmar Probably segfaults even before that, for an unchecked NULL in `fp`. – Yunnosch May 05 '18 at 12:01
  • @Yunnosch If the file exists, why would he get NULL in fp? – Barmar May 05 '18 at 12:03
  • @Barmar I have seen your condition/assumption. But there IS a segfault and I don't see another way of provoking one. So what makes you believe that the file exists and is readable? Also I wanted to imply that checking for NULL is always a good idea... – Yunnosch May 05 '18 at 12:06
  • @Barmar : Yes but while writing in solaris i did not put that print message – Kanishk Viman May 05 '18 at 12:07
  • 1
    If you're talking about a different program, how are we supposed to explain what it does? – Barmar May 05 '18 at 12:08
  • @Someprogrammerdude : But without segfault i will get those print messages right ? – Kanishk Viman May 05 '18 at 12:08
  • 1
    You'll get them when the program exits, since that will flush the buffer. – Barmar May 05 '18 at 12:09
  • BTW, you wrote your code in a [source code editor](https://en.wikipedia.org/wiki/Source_code_editor), not in `gdb`. Then you [compiled](https://en.wikipedia.org/wiki/Compiler) your code into some [executable](https://en.wikipedia.org/wiki/Executable), and you should have shown your compilation command in your question. At last you run that executable with the `gdb` debugger. Terminology is important – Basile Starynkevitch May 06 '18 at 05:47
  • Most likely, the call to `fopen()` is failing: suggest the next code after that statement be: if( !fp ) { perror( "fopen failed" ); exit( EXIT_FAILURE ); }` – user3629249 May 06 '18 at 21:52
  • regarding this kind of statement: `printf("jkjkkjkj2");` end the format string with '\n' so the system immediately flushes the `stdout` buffer to the terminal – user3629249 May 06 '18 at 21:57

2 Answers2

3

As answered by Yunnosch, you probably forgot to check against failure of fopen(3). A better habit is to always check that, at least by coding:

  fp = fopen("abc.txt","r"); 
  if (fp == NULL) { perror("fopen abc.txt"); exit(EXIT_FAILURE); };

and take the habit of doing at least that everywhere. Using perror(3) (or strerror(3) with errno(3)) is a useful habit to get, since you want some reason related to the failure (given by errno perhaps thru perror).

More generally, always read the documentation of functions that you are using (for standard functions, at least on some reference website, and possibly in the C11 standard n1570), and take care of handling their failure (at the very least, by checking against failure and exiting with a useful message to stderr); for Unix functions, see their man pages (on Linux, start on intro(2) and intro(3); for Solaris, start with intro(2) & intro(3)..). In your Unix terminal, try also man fopen ... For POSIX standard, start here.


what intrigues me is the absence of the messages that I am trying to print on the screen.

That is simple. stdout is buffered (see also setvbuf(3)), and often line-buffered. So a printf which does not end with a \n has its output still inside the buffer, and not yet on the screen. The habit to get is to almost always end your printf(3) control format string with a newline, or else to flush the buffer explicitly using fflush(3).

For a newbie, there are few reasons to avoid ending your printf with an explicit \n. So use instead

printf("jkjkkjkj\n");

Otherwise, call fflush(NULL); quite often in your program. BTW, for these buffering reasons, fflush(NULL) should be done before calls to system(3), fork(2), execve(2) and other important program-wide functions.


optimized out written near the line no

That probably happens in the C standard library itself (e.g. in getc from some libc.so), which is usually not compiled with debug information. In practice, trust your C standard library: you are much more likely to have bugs in your code that in libc.

Your own source code should be compiled with gcc -Wall -Wextra -g (asking the GCC compiler to give all warnings and debug info in DWARF format, usable by the gdb debugger) and you need to improve your code to get no warnings at all before using the gdb debugger.

Be aware of undefined behavior, spend several hours reading about UB, and be scared of UB.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

Try guarding against NULL in fp and for good measure make sure the debug output gets printed (as in comment by Some Programmer Dude).

#include <stdio.h>

int main(void)
{    
   int p , n;
   FILE *fp;

   printf("jkjkkjkj2\n");
   fp = fopen("abc.txt","r"); 

   if (NULL != fp)
   {
      while ( (n = getc(fp))!= EOF)
      {
           printf( "the chareacter here is %d \n", n);
      }
      n = fclose(fp);
   } else
   { 
       printf("File opening failed somehow!\n");
   }
   return 0;
}

Note the nice touch (by Basile Starynkevitch) to only close what was successfully opened.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54