Segmentation fault found but message before that is being optimized out - c

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.

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.

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.

Related

Segmentation Fault when reading from file - fgets()

Trying to read from a file to use in a small game I've created. I'm using the fgets function. It's returning a Segmentation Fault, not sure why.
The file it's reading, just contains "20 10" in a txt file as this is the map size.
My readfile function is shown below
if (argc == 2) {
f = fopen("map.txt", "r");
if (NULL == f) {
printf("File cannot be opened.");
}
while (fgets(fileRead, 50, f) != NULL) {
printf("%s", fileRead);
}
fclose(f);
}
The if (argc == 2) can be ignored, this is just to make this section run, as I'm modifying a file so just running this function by satisfying that if statement.
I am fairly new to C, so apologies if I'm missing something minor. Worth noting I'm programming in C89 and using the -Wall -ansi -pedantic compile options, as this is University work and the tutors want us to do C89.
EDIT:
char userInput, fileRead[50];
FILE* f;
Declaration of variables.
Assuming that your problem is indeed in your posted code and not somewhere else in the program, then I believe that your problem is caused by the following issue:
After calling fopen, you check the return value of the function immediately afterwards, to verify that it succeeded. However, if it doesn't succeed and it returns NULL, all you do is print an error message to stdout but continue execution as if it succeeded. This will cause fgets to be called with NULL as the stream argument, which will invoke undefined behavior and probably cause your segmentation fault.
In the comments section, you raised the following objection to this explanation:
However it doesn't print the error message anyway and still segmentation faults, so I think the problem isn't here?
This objection of yours is flawed, for the following reason:
When a segmentation fault occurs, execution of the program is immediately halted. The content of the output buffer is not flushed. This means that output can get lost when a segmentation fault happens. This is probably what is happening in your case.
If you want to ensure that the output actually gets printed even in the case of a segmentation fault, you should flush the output buffer by calling fflush( stdout ); immediately after the print statement. Alternatively, you can print to stderr instead of stdout. In constrast to stdout, the stream stderr is unbuffered by default, so that it does not have this problem.
You can test whether my suspicion is correct by changing the line
printf("File cannot be opened.");
to
printf("File cannot be opened.");
fflush( stdout );
or to:
fprintf( stderr, "File cannot be opened." );
If the error message now gets printed, then this probably means that my suspicion was correct.
In any case, I recommend that you change the lines
if (NULL == f) {
printf("File cannot be opened.");
}
to the following:
if (NULL == f) {
fprintf( stderr, "File cannot be opened." );
exit( EXIT_FAILURE );
}
That way, the program will exit immediately if an occur occurs, instead of continuing execution.
Please note that the code posted above requires you to #include <stdlib.h>.

Calling yyrestart function in bison with no arguments causing sigsev on El Capitan

I'm curious about the function signature for yyrestart - namely in the lexer file I see that the signature is:
void yyrestart (FILE * input_file )
In my code I use yyrestart to flush the buffer, but I haven't been passing it any argument, it's just been empty:
yyrestart();
Which is currently working on every system we test on except for the latest version of OS X. Stepping through with GDB, it's clear on my rhel machine that just calling with no argument sets the file pointer to NULL:
yyrestart (input_file=0x0) at reglexer.c:1489
Whereas on El Capitan it comes through as garbage, which is causing the mem error later in generated code:
yyrestart (input_file=0x100001d0d) at reglexer.c:1489
I can't for the life of me figure out where yyrestart() is defined. Is there some macro in yacc/flex that defines the behavior for calling yyrestart with no arguments? If not, how is this even compiling?
*********** EDIT to Clarify the Compiling Question ************
As a small snippet to see what I'm talking about - this is what I have in a my .y file, which is executing the parser (this is a SLIGHT modification of what's this example):
int main() {
FILE *myfile = fopen("infile.txt", "r");
if (!myfile) {
fprintf(stderr, "can't open infile.txt\n");
return 1;
}
calcYYin = myfile;
do {
calcYYparse();
} while (!feof(calcYYin));
calcYYrestart();
return 0;
}
I can build that repository with whatever I want passed in as arguments to calcYYrestart() on that line. Substituting
calcYYrestart('a', 1, 5, 'a string');
still lets me compile the entire program using make (but a get a segv with bad input). But looking through the generated parcalc.c file, I don't see anything that would allow me to call calcYYrestart with anything except for a file pointer. I only see this as the prototype:
void calcYYrestart (FILE * input_file );
Where's the magic happening with the compiler that lets me put whatever I want as arguments to that generated function?
You are expecting C to gently lead you through the maze, holding your hand, chiding you when you err and applauding your successes.
These may not be unreasonable expectations for a language, but C is not that language. C does what you tell it to do, nothing more, and when your instructions fall short of clarity, it simply lets you fall.
Although, in its defense, you can ask it to be a bit more verbose. If you specify -Wall on the command line (at least with gcc and clang), the compiler will provide you with some warnings. [See note 1.]
In this case, it probably would have warned you that calcYYrestart was not declared, which would make it your responsibility to get the arguments right. The function is declared and defined in the lexer, but here you are using it in the parser, which is a separate compilation unit. You really should declare it in the parser prologue, but nothing will enforce the correctness of that declaration. (C++ would fail to link in that case, but C does not record argument types in the formal function name.)
It's worth noting that there are many problems with the sample code you are basing your work on. I'd suggest looking for a better bison/flex tutorial, or at least reading through the sections in the flex manual about how input is handled.
Here, I've added some annotations to the original example, which shows the calc.y bison input file:
/* This is unnecessary, since `calcYYparse` is defined in this file.
extern int calcYYparse();
*/
extern FILE *calcYYin;
/* Command line arguments are always good */
int main(int argc, char** argv) {
/* If there is an argument, use it. Otherwise, stick with stdin */
/* There is no need for a local variable. We can just use yyin */
if (argc > 1) {
calcYYin = fopen(argv[1], "r");
if (!calcYYin) {
fprintf(stderr, "can't open infile.txt\n");
return 1;
}
}
/* calcYYin = myfile; */
/* This loop is unnecessary, since yyparse parses input until it
* reaches EOF, unless it hits an error. And if it hits an error, it
* will call calcYYerror (below), which in turn calls exit(1), so it
* never returns.
*/
/* do { */
calcYYparse();
/* } while (!feof(calcYYin)); */
return 0;
}
void calcYYerror(const char* s) {
fprintf(stderr, "Error! %s\n", s);
/* Valid arguments to `exit` are 0 and small positive integers. */
exit(EXIT_FAILURE);
}
Of course, you probably don't want to just blow up the world if you hit a syntax error. The intention was probably to discard the rest of the line and then continue the parse. In that case, for obvious reasons, callYYerror should not call exit().
By default, after yyerror is called, yyparse returns immediately (after cleaning up its local storage) with an error indication. If you want it to instead continue, then you need to use an error production, which would be the best solution.
You could also simply call yyparse again, as in the example. However, that leaves an unknown amount of the input file in the flex buffer. There is no reason to believe that the buffer contains exactly the rest of the line in error. Since flex scanners typically read there input in large chunks (except for interactive input), resetting the input file with yyrestart will discard a random amount of input, leaving the input file pointer at a random position in the file, which probably does not correspond with the beginning of a new line.
Even if that were not the case, as with unbuffered (interactive) input, it is entirely possible that the error was detected at the end of a line, in which case the new line will already have been consumed. So discarding to the end of the current line will result in discarding the line following the error.
Finally, the use of feof(input) to terminate input loops is a well-known antipattern, and should be avoided in favour of terminating when an EOF is encountered while reading input. In the case of flex-generated scanners, when EOF is detected, the current input is discarded, and then (if yywrap doesn't succeed in creating a new input), the END indication is returned to the parser. By then, yyin is no longer valid (because it was discarded), and calling feof on it is undefined behaviour.
Notes
You get even more warnings by also specifying -Wextra. And you can make the compiler a little stricter by telling it to use the latest standard, -std=c11, instead of the 1989 version augmented with various gcc extensions, mostly now outdated.)

Why gcc does not give a warning or error when invalid mode is used in fopen()?

I am practicing some practice questions in FILE IO in C. Below is one of the programs.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char fname[]="poem.txt";
FILE *fp;
char ch;
fp = fopen ( fname, "tr");
if (fp == NULL)
{
printf("Unable to open file...\n");
exit(1);
}
while((ch =fgetc(fp)) != EOF)
{
printf("%c",ch);
}
printf("\n");
return 0;
}
As you can see in the statement
fp = fopen ( fname, "tr");
The mode "tr" is not a valid mode (as I understand). I was expecting gcc to give an error (or a warning) while compiling the above program. However, gcc does not give any error (or warning) while compiling it.
However, as expected, when i run the program it exits printing "Unable to open file..." which means fopen() returned NULL , because there was error while opening file.
-bash-4.1$ ./a.out
Unable to open file...
-bash-4.1$
(The file poem.txt exists so this is because of the invalid mode given to fopen(). I checked by changing the mode to "r" and it works fine displaying the content of "poem.txt")
-bash-4.1$ ./a.out
THis is a poem.
-bash-4.1$
I was expecting gcc to give an error (or warning) message for the invalid mode.
Why gcc does not give any error (or warning) for this ?
the compiler doesn't check what you do, it only checks the syntax.
However, at run time, if the code is written like so:
#include<stdio.h>
#include<stdlib.h>
int main()
{
char fname[]="poem.txt";
FILE *fp;
char ch;
fp = fopen ( fname, "tr");
if (fp == NULL)
{
perror( "fopen for poem.txt failed");
exit( EXIT_FAILURE );
}
while((ch =fgetc(fp)) != EOF)
{
printf("%c",ch);
}
printf("\n");
return 0;
}
then a proper error message is output:
...$ ./untitled
fopen for poem.txt failed: Invalid argument
This is Undefined Behavior:
Per Annex J.2 "Undefined Behavior", it is UDB if:
—The string pointed to by the mode argument in a call to the fopen function does not exactly match one of the specified character sequences (7.19.5.3).
Although Annex J is informative, looking at §7.19.5.3:
/3 The argument mode points to a string. If the string is one of the following, the file is open in the indicated mode. Otherwise, the behavior is undefined.
Basically, the compiler can blow you off here - a standard library function name (and behavior) can be used outside of the inclusion of a standard header (for example, non-standard extensions, completely user-defined behavior, etc.). The Standard specifies what a conforming library implementation shall include and how it shall behave, but does not require you to use that standard library (or define behavior for a specific implementation explicitly specified as UDB territory: at this point, if your parameter types match it's a legal function call).
A really good lint utility might help you here.
How is the compiler supposed to know what the valid arguments for a function are?
To do it you'd be building too much knowledge in the compiler - it would have to recognize functions and their parameters by name. What if you want to override the function? What if different modes are valid on different platforms?
In Windows programming, "tr" is a valid mode is not a valid mode, although "rt" is. The t means text and the r means read. (If you are using gcc and linking to MS's C runtime then you will be able to use this).
However you still don't see t very often because it is the default and therefore redundant; the other option for this setting is b meaning binary. But MS do seem to explicitly use t in their examples to make it clear that translation is intended.
The behaviour of text mode and binary mode for a stream is implementation-defined, although the intent is that binary mode reads the characters exactly as they appear on disk, and text mode may perform translations relevant to text processing; most famously, converting \r\n in MS text files to \n in your program.

fclose() always returns EOF

I have a function that reads integers with certain format from a file.
It works fine as desired, but whenever I tried to close the file with fclose(),
fclose() always returns EOF.
Any suggestions why? I am a student and still learning.
I have put the code below. Please let me know if you need the "processing" code. Thanks :)
// Open the file
FILE *myFile = fopen(fileName, "r");
if(myFile == NULL){
//Handle error
fprintf(stderr, "Error opening file for read \n");
exit(1);
}
while(myFile != EOF)
{
// read and process the file
// this part works.
}
// always returns EOF here. WHY?
if (fclose(myFile) == EOF) {
// Handle the error!
fprintf(stderr, "Error closing input file.\n");
exit(1);
}
printf("Done reading the file.");
EDIT:
Thank you for all the replies. Sorry I cannot post the code as this is part of my homework. I was trying to get some help, I am not asking you guys to make the code for me. Posting code is illegal according to my Prof (since other students can see and probably copy, that's what he told me). I can only post the code after Sunday. For now, I will try to modify my code and avoid using fscanf. Thanks and my apology.
This:
while(myFile != EOF)
is actually illegal (a constraint violation). Any conforming C compiler is required to issue a diagnostic; gcc, by default, merely issues a warning (which does qualify as a "diagnostic").
If gcc gave you a warning, you should pay attention to it; gcc often issues warnings for things that IMHO should be treated as fatal errors. And if it didn't give you a warning, you're probably invoking it with options that disable warnings (which is odd, because it does produce that warning by default). A good set of options to use is -Wall -Wextra -std=c99 -pedantic (or adjust the -std=... option to enforce a different version of the standard if you like).
myFile is of pointer type, specifically FILE*. EOF is of type int, and typically expands to (-1). You cannot legally compare a pointer value to an integer value (except for the special case of a null pointer constant, but that doesn't apply here.)
Assuming the program isn't rejected, I'd expect that to result in an infinite loop, since myFile would almost certainly never be equal to EOF.
You could change it to
while (!feof(myFile))
but that can cause other problems. The correct way to detect end-of-file while reading from a file is to use the value returned by whatever function you're using read the data. Consult the documentation for the function you're using to see what it returns when it encounters end-of-file or an error condition. The feof() function is useful for determining, after you've finished reading, whether you encountered end-of-file or an error condition.
Since there is nothing that you can do to a regular file open in read-only-mode that would cause a fclose to error out, you very probably have a bug in the code you didn't show which is stomping on the myFile structure.
Also the test myFile != EOF will never be true because you set it to the return of fopen which will never give you EOF and you already checked it for NULL Did you mean something like:
while((c = fgetc(myFile)) != EOF) {
// do stuff
}
What the errno said? add this to your code:
#include <errno.h>
#include <string.h>
if (fclose(myFile) == EOF) {
// Handle the error!
fprintf(stderr, "Error closing input file. and errno = %d, and error = %s\n", errno, strerror(errno));
exit(1);
}
Hope this help.
Regards.
while(myFile != EOF)
{
// read and process the file
// this part works.
}
If this part is ok then
fclose(myFile);
definitely return you EOF.Because the while loop terminates only myFile == EOF(this is a wrong comparison, do not ignore warnings).comparision between pointer and int.As EOF is a macro defined in stdio.h file And according to glibc it -1.Your loop terminates that means your myFile pointer changed to EOF some whire.This is your mistake.
just go through your code you must be change the FILE pointer myFile which should not be over written by you As it point to a file structure
which is used for all file operation.
NOTE
myFile which is a pointer to a file should not be used as lvalue in any assignment statement.
Change while(myFile != EOF){...} by while(!feof(myFile)){...}
myFile is a pointer to a FILE struct (a memory address). Not a "end of file" indicator.

runtime error (SIGSEGV)

can anyone tell me whats wrong in the following program that accepts 1 or 2 digit integers untill it encounters the number 42 after which it prints the previously entered numbers??when i upload this to the sphere online judge site it says compilation successful but runtime error (SIGSEGV).
#include <stdio.h>
int main()
{
int i;
FILE *fp;
fp=fopen("\\db.txt","w+");
if(fp==NULL)
{
printf("file not exitsts and cant be created");
system("exit");
}
while(1)
{
scanf("%d",&i);
if(i==42)
break;
else
{
fprintf(fp,"%d\n",i);
}
}
fclose(fp);
fp=fopen("\\db.txt","r+");
if(fp==NULL)
{
printf("file not exitsts and cant be created");
system("exit");
}
fscanf(fp,"%d",&i);
printf("%d\n",i);
while((!feof(fp)))
{
fscanf(fp,"%d",&i);
if(!feof(fp))
printf("%d\n",i);
}
fclose(fp);
return 0;
}
It seems like you're trying to answer this: http://www.spoj.pl/problems/TEST/ . This problem certainly does not require you to read or write anything from a file, and their server may not allow you to open files on its disk. Even if it does, you're trying to use a windows-style path (with a backslash) on what may be a non-Windows server. And even if it does allow file creation and windows-style path separation, you are trying to create your file in the filesystem root directory, and they almost certainly do not allow file creation there.
Combined with the system("exit") issue that everyone pointed out where it doesn't actually exit the program, this will cause you to receive a NULL file pointer and crash when you try to use it.
Re-read the problem description - you're over-thinking it. It doesn't say anywhere that you have to wait until you get a 42 to print out the other numbers. All you have to do is print back what is entered until you get a 42. That should make the solution much simpler. It's not supposed to be even a mildly challenging problem; it's just supposed to familiarize you with their system.
I don't know what you think:
system("exit");
will do, but the way to exit a program in C is:
exit(1);
You should replace
system("exit");
with
exit(1);
or, because you're already in main:
return 1;
I suspect the SIGSEGV is caused because you cannot write to the file \\db.txt, but the program continues because system("exit") is not causing it to terminate.
On an semi-related note, SIGSEGV is usually a Unix signal, and path separators on Unix are / rather than \.
I don't know precisely the cause of the SEGV, but I guess it is because the input doesn't match what you expect. In any case, this line doesn't do what you think it does:
system("exit");
at which line do you receive the error?
is your empty #include intended? i think it should mean #include
have you got the error for every input or just for 42?
regards
SIGSEGV is an access violation error, which indicates a null pointer. Since system("exit") isn't doing anything, fp is getting set to null, and then when you try to use that pointer (for example with fprintf())... boom, your program crashes.
Replace system("exit") with return 1 (or whatever error code you desire), that should fix it.
$ gcc -Wall test.c -o test
test.c: In function ‘main’:
test.c:8: warning: implicit declaration of function ‘system’
$ ./test
1
2
3
10
42
1
2
3
10
But yes, I do agree that the system("exit") does not what you expect. What you are exiting from, with that call, is a subshell that is spawned by your program, and then goes on. From the system man page
The system() function hands the
argument command to the command
interpreter sh(1). The calling
process waits for the shell to finish
executing the command, ignoring SIGINT
and SIGQUIT, and blocking SIGCHLD.

Resources