runtime error (SIGSEGV) - c

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.

Related

Segmentation fault found but message before that is being optimized out

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.

How to properly write to a bash fifo in C?

I'm attempting to write an output to a bash fifo so I can pipe it into another program. However, as soon as I run it I get a segmentation fault. Any thoughts? (C amateur here)
(errorout in this case a global variable and is successfully called elsewhere)
void print_log(){
printf("about to creat file pointer");
FILE* image_fifo;
printf("open fifo");
image_fifo = fopen("image",O_WRONLY);
if(image_fifo == NULL){
printf("unable to open fifo");
}//end if
else{
printf("writing to fifo");
int j;
for(j=0;j<1024;j++){
fprintf(image_fifo,"%u",errorout[j]);
}//end for
}
fclose(image_fifo);
for now, reading it out using this: (isn't python great?)
with open("image","r") as f:
print(f.read())
I think the segmentation fault is caused by this:
image_fifo = fopen("image",O_WRONLY);
This is for calling Linux system style open() from sys/stat.h (or fcntl.h), where the second parameter is an int which indicates flags (and O_WRONLY is indeed defined to an int value in the header file). In C fopen() from stdio.h you do this with a char *, e.g. fopen("name", "w");.
To be sure next time include anything the program prints before ending. You might also want to look at valgrind output; it might give you some clues about what's gone wrong.
As for "bash style fifo", I am not sure what you're trying to do, but if you're just trying to write to a file, you're doing it almost correctly. If you're trying to make a pipeline (I've heard someone call them fifo's too, so might be the case), you should look at the libpipeline library and its usage.

How to solve exit code 139 error when reading from file on unix

So I believe this is just a problem on unix and that it occurs at the first fscanf if the Clion debugger was right, but I don't know why I get the error- Process finished with exit code 139 (interrupted by signal 11: SIGSEGV) - why?
struct loginInformation
{
char username[USERNAME_LENGTH];
char password[PASSWORD_LENGTH];
int type;
}accounts[NUM_OF_ACCOUNTS];
void createAccountsFromFile()
{
FILE *input = fopen("accounts.txt", "r");
int counter;
for(counter = 0; counter < NUM_OF_ACCOUNTS; counter++)
{
fscanf(input, "%s", accounts[counter].username);
fscanf(input, "%s", accounts[counter].password);
fscanf(input, "%d", &accounts[counter].type);
}
}
int main()
{
createAccountsFromFile();
}
accounts.txt
user1
pass1
0
user2
pass2
1
user3
pass3
2
user4
pass4
3
It means the program crashed before it exited. You need to debug the program. For example, you need to check whether the file is successfully opened after fopen.
SIGSEGV are not always thrown due to a root cause of memory access problems...
Perl throws a 139 on Unix usually because of file I/O. You might have accidentally deleted your input files.
TL;DR: Your program tried to access a memory location it had no permissions to access, so the operating system killed it.
First: The code "139" doesn't matter, forget about the number. Your program was terminated after "getting a SIGSEGV", or a signall regarding a segmentation violation. Read about what that means here:
What causes a SIGSEGV
(never mind that question is about C++, same idea.)
Now, why would this happen? You must be making some assumptions you shouldn't be. Looking at your code, it might be:
Reading a very long string from the file which exceeds the bounds of the loginInformation array - and perhaps even the bounds of the memory region allocated to your program overall.
Scanning from an invalid-state/uninitialized/null file descriptor, as in #xuhdev's answer
(Unlikely/impossible) Ignoring some error generated by one of the fscanf() calls (you need to check errno if a scan failed).
I think that covers it although maybe I missed something. Instead of speculating you can actually check what happened using a debugger on the core dump:
How do I analyze a program's core dump file with GDB when it has command-line parameters?
On Perl programmation RC 139 caused by "Out of memory" for me.
Because there have been too much data in a variable (millions).
I have done a segmentation manualy by release (undef) this variable regularly.
This solved this.

C write() function not working

I am trying to write into a file, but it is not working. I can open a file, but while writing in the file using write function, tt is writting in the stdout itself, and the content of the file I opened remain unchanged.
#include<stdio.h>
#include<sys/file.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<limits.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/uio.h>
main() {
char fn[30];
int fd,i=0;
int actualbytes,bytesstored;
char buffer[100];
printf("\nEnter the filename with path");
scanf("%s",fn);
if(fd=open(fn,O_WRONLY|O_CREAT,S_IWUSR|S_IWUSR)<0)
{
perror("open");
exit(0);
}
else
{
write(stdout,"\n\nEnter the contents for the file\n");
write(stdout,"press CTRl+D at the end of the file\n\n");
fflush(stdout);
while((buffer[i]=getc(stdin))!=EOF) i++;
buffer[i]='\0';
bytesstored=sizeof(buffer);
if(actualbytes=write(fd,buffer,bytesstored)<0)
{
perror("write");
exit(0);
}
else
{
write(stdout,"\n\nfile is opened successfully");
write(stdout,"\nThe contents are written"); fflush(stdout);
}
if(close(fd)<0)
{
perror("close");
exit(0);
}
else
printf("\nfile is closed");
}
}
< has higher precedence than =.
if((fd=open(fn,O_WRONLY|O_CREAT,S_IWUSR|S_IWUSR))<0)
There are a lot of problems with this code. Make sure you enable warnings on your compiler, it should complain about quite a few things:
write() is in unistd.h. You're not including that, so your program cannot be correct.
Once you include that, you'll notice (with warnings enabled), that you're calling it incorrectly at least 5 times: stdout is not a file descriptor, it's a FILE*.
Use the printf() family of functions to print things on the console.
Second big problem is your if statements that have assignments in them.
if (a = b < 0) { ... }
is equivalent to:
if (a = (b < 0)) { ... }
So it's not doing what you think it is. You need to use parenthesis:
if ((fd = open(...)) < 0) { ... }
Note: you're always writing the full buffer to the file. Not all of it has been initialized. That doesn't sound like what you're after. Try only writing the data that you've read (you have that stored in i).
Please note, from stdin(3):
#include <stdio.h>
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
stdin, stdout, are standard IO FILE * streams, for use with fprintf(3), fgets(3), and so forth.
read(2) and write(2) take filedescriptors (which are represented as ints).
Keeping the C-supplied standard IO streams and the Unix-supplied filedescriptors separate in your mind is vital to sane Unix programming; sorry it's complicated :) but it's well worth becoming an expert.
I suggest changing all your write(stdout,... to fprintf(stdout,....
Ah, I see Ignacio has spotted the core problem :) it's hard to put one past him.
Another issue to worry about, your scanf() call doesn't limit the length of input to the size of your buffer. Someone could overflow your buffer and scribble data of their choosing all over memory. It's not a big deal when you're learning, but this kind of bug is exactly how the first Internet worm infected some new machines, so it is well worth not making the same mistake again.
And the last issue I spotted is how you're writing out your buffer:
buffer[i]='\0';
bytesstored=sizeof(buffer);
if(actualbytes=write(fd,buffer,bytesstored)<0)
sizeof(buffer) is always going to return 100, because that is what you declared for buffer at the start of your program. So replace with this:
buffer[i++]='\0';
if(actualbytes=write(fd,buffer,i)<0)
As the others noted, there are a lot of problems with your code. Always instruct your compiler to show warnings. If you are using GCC then pass the argument -Wall to show all warnings. Now, if I do so with your code it suggests the following:
write.c:9: warning: return type defaults to ‘int’
write.c: In function ‘main’:
write.c:18: warning: suggest parentheses around assignment used as truth value
write.c:25: warning: implicit declaration of function ‘write’
write.c:34: warning: suggest parentheses around assignment used as truth value
write.c:45: warning: implicit declaration of function ‘close’
write.c:55: warning: control reaches end of non-void function
The first one means that your function main() defaults to int but you should always state a return type. On line 18 and 34 you need parentheses around the assignments before testing with < (as Ignacio said above). On line 25 and 45 it can't find the prototype for write() and close(), so you need to include the right header files. The last one means that you need to have a return statement (because it defaulted to type int).
just include and the warning will disappear.

Reading from files passed as command line arguements

I am trying to parse a given textfile, but so far, my program does not seem to be reading properly.
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fr; //file pointer
int buildingFloors = 1;
printf("sanity check\n");
fr = fopen (argv[0], "r");
fscanf(fr, "%d", &buildingFloors );
printf("%d\n", buildingFloors);
fclose(fr);
return 0;
}
I compile the program and run it on my redhat linux machine with the following command:
./sjf file.text
file.text is a text document with a "4" as the first character. So I would expect my output to be
sanity check
4
However, when I run my program I instead get
sanity check
1
Which implies that fscanf didn't properly read in the first character -- 4. Do I have some syntax error that's preventing the expected code functionality? Am I supposed to scanf for a character, and then convert that to an int somehow?
argv[0] is the name of the program (./sjf in your case), so you're trying to read in your own program's executable. Use argv[1] instead to get the first real program argument.
One thing which immediatly comes to mind is that the program args include the executable name as the first element
argv[0] is "sjf"
argv[1] is "file.text"
so you should be using
fr = fopen (argv[1], "r");
Remember when debugging to always try and narrow the problem down, if you know the location of the error the cause often becomes obvious or at least investigatable.
In this case you should check argc >= 2, print out argv[1] to ensure you are trying to open the right file, then also check that the file was opened successfully.
Finally check the fscanf error codes to see that fscanf was able to read the number.
Your code looks clear and straight-forward, but there is one important thing missing: error handling.
What happens if the file you want to open does not exist? fopen returns NULL in that case.
What happens if the file does not start with a number? fscanf returns the number of fields that have been successfully read, so you should check that the return value is at least 1.
You need to somehow handle these cases, probably by printing some error message and exiting the program. When you do that, be sure to include the relevant information in the error messages. Then you will find the bug that the other answers have already mentioned.

Resources