Segmentation fault when opening file in C? - c

I'm very new to programming and I'm trying to write code that reads "numbers.tsv4" (.tsv4 means tab separated values, 4 to a line) and puts the numbers into an array. Right now I'm just focusing on counting the amount of numbers in a file, so I can initialize the array size.
int main(void)
{
int cur;
FILE* spData;
int size=1;
spData = fopen("numbers.tsv4", "r");
while ((cur = fgetc(spData)) != EOF) {
if ((cur = fgetc(spData)) == '\t') {
size++;}
}
fclose(spData);
printf("%d", size);
return;
}
I keep getting a segmentation fault and I've changed so many things to try to figure it out. Could someone give me a hand? Thanks!

The structure with your while statement is the problem. At the beginning of each iteration, you are already getting the next character with fgetc() and assigning it to cur. Then inside the loop, in the if(...) statement, you discard the cur by calling a new fgetc() and assigning the result to cur. So, change it in the following way:
while ((cur = fgetc(spData)) != EOF) {
if (cur == '\t') {
size++;}
}
You see, when you try to invoke the fgetc() twice (both in while(...) and if(...)), you probably get the EOF in the if(...) statement. Then in the next iteration with the while(...) statement, you try to access somewhere out of file, which gives you the segmentation fault.

Related

Getting the Contents of a File and Putting it into a String in C

I am trying to make a function in C that takes the contents of a file and returns the contents as a string. I got it to works except for one odd detail. This is the current code:
char *getFileContents(const char *filePath) {
if (filePath == NULL) return NULL;
char buffer[1000];
char character;
int count = 0;
FILE *f = fopen(filePath, "r");
while (character != EOF) {
count++;
character = fgetc(f);
printf("%c\n", character);
}
count--;
fclose(f);
FILE *F = fopen(filePath, "r");
char *str = (char*) malloc ( sizeof(char) * (count + 1 ) );
char *line = fgets(buffer, 1000, F);
while (line != NULL) {
strcat(str, line);
line = fgets(buffer, 1000, F);
}
fclose(F);
return str;
}
In the first while loop, I added a printf statement for error checking that I do not need anymore. The function works fine with the printf statement but whenever I comment it out or remove it I get a segmentation fault. I've used gdb to debug and try to find the issue.
I can step through the whole function but the moment it reaches the return str at the end I get a segmentation fault. I'm not sure why I'm experiencing this problem.
One problem is that you never initialize the memory buffer returned by malloc() -- you are apparently expecting it to be all-zeros (or at least start with a 0-byte) so that you can fill it in with calls to strcat(); but malloc() doesn't guarantee the contents of the memory it returns will be zeroed-out, so you are likely starting with some garbage-bytes already present in the str buffer, which means that as you add more bytes from the file, you will likely write past the end of the buffer and invoke undefined behavior (and likely crash).
The simple fix would be to do a str[0] = '\0'; after the call to malloc() (or if you're paranoid, you could do a full memset(str, 0, count+1);). Or alternatively you could allocate the memory with a call to calloc() rather than malloc(), as calloc() does guarantee that the returned buffer will be all zero-initialized bytes.
The commenting of a line causing a segmentation fault is the manifestation of Undefined Behaviour.
The initial comparison of character with EOF reads an uninitialized, garbage value.
char character;
/* ... */
while (character != EOF) {
/* ... */
The results of this program cannot be reasoned about after this occurs. A random SIGSEGV is par for the course.
Additionally, fgetc returns an int. EOF is a negative value, and cannot be properly represented if char is unsigned.
Try changing your loop construct.
int character;
/* ... */
while (EOF != (character = fgetc(f))
count++;
Note, you should also check that the return value from fopen was not NULL, and react accordingly.
FILE *f = fopen(filePath, "r");
if (!f) {
perror(filePath);
return NULL;
}
I got rid of the first while loop that counts the number of characters in the file and moved it to a different function. The function I moved it to will be responsible for counting the characters. This way I would only need one fopen and fclose statement in the getFileContents function. This solved my problem and everything is working as intended.

Can't find the reason why my loop doesn't terminate

Good morning.
I have received a task to build a C program, and I've encountered an annoying problem.
I'm trying to scan an unknown length string, which includes only numbers, '-' and spaces, and do something with that string.
The problem is, while scanning it, the program just stops doing anything after finding a minus. It doesn't want to scan any more characters afterwards.
The part where the loop doesn't being terminated:
while ((c = getchar()) != '\n' && c != EOF)
{
pStr[i++] = (char)c;
if (c == ' ')
numCounter++;
//if i reached maximize size then realloc size
if (i == current_size)
{
current_size = i + len_max;
pStr = realloc(pStr, current_size);
if (pStr == NULL)
{
printf("Memory allocation failure. \n");
exit(2);
}
}
}
pStr[i] = '\0';
.
.
.
When I was scanning a line that doesn't include minuses, the program did well. The only problem is while scanning a minus.
While debugging, this is the part where my program gets into infinite loop.
Can anyone please point me where's my mistake, so that the program could finally read a minus?
In general, the program gets a line of unknown length of numbers, minuses and spaces. The program would build a polynum. There is a Monom struct, and I want to build an array that would store, in each Monom value, the coefficient (index 0) and the power (index 1).
So my plan was to scan an unknown length string, check where I have numbers, and build a dynamic Monom array that will store the values. Ofcourse I have many more functions that are necessary, like converting a char value to int number, etc.
So far my only problem is the minus part. That could be very helpful if anyone can point me where's my mistake.
Thanks in advance!

Any idea why my print function prints and then runs forever?

Any idea why my print function prints and then runs forever before crashing?
void readDataFile(){
FILE* fp = fopen("text.txt","r");
int t=0;
while(fp !=EOF){
text[t] = fgetc(fp);
printf("%c",text[t]);
t++;
}
fclose(fp);
}
Check compiler warnings (e.g.: gcc -Wall file.c). You should get a warning on the line "while(fp !=EOF){" that you are comparing a pointer to an integer. The function works if you rewrite the while statement as:
while ((text[t] = fgetc(fp)) != EOF){
printf("%c",text[t]);
t++;
}
Notice that you need to look for EOF in the character retrieved by fgetc, not in the file pointer fp.
You need to start the loop with a condition that is true and then end it when it becomes false. Otherwise the loop does not know when the condition becomes false i.e. it is always true and therefore it continues to loop. My obs.

segmentation fault C finite state machine

I am relatively new to C programming and I am trying to make a delimiter checker, but for some reason every time I run my code and it gets my input to check for delimiters, it has a segmentation fault (core dumped) error.
Below is the code of the main program:
int
main (void)
{
char* mystring;
printf ("Please enter a string\n");
gets(mystring);
if (fsm(mystring))
{
printf ("All matched");
}
}
It seems like it never enters the subprogram fsm though, because I put in a printf right at the beginning of the subprogram and it never shows up. It does ask for my input though and prints it back out if I put the printf in the main program before the subprogram line.
Here is my prototype:
boolean fsm(char[]);
and here is the beginning of the subprogram if that is any help:
boolean fsm (char mystring[])
{
printf("here\n");
int counter = -1;
int state = 0;
c_stack top;
c_init_stack (&top);
while (1)
{
switch (state)
{
case 0:
counter = counter + 1;
if (is_open (*mystring))
state = 1;
else if (is_close (*mystring))
state = 2;
else if (mystring = '\0')
state = 3;
else
state = 4;
break;
You are trying to read into an uninitialized char*. Just declaring char *mystring doesn't give you a string to work with: you'll need to allocate space for the string.
Either:
char *mystring = malloc(MAX_STRING_LENGTH);
Or:
char mystring[MAX_STRING_LENGTH];
Once you have a buffer, use fgets instead of gets. fgets allows you to specify an upper-bound on the number of characters read, so fgets along with something like MAX_STRING_LEN you'll be able to accept only as much data as your buffer will hold.
As it is, since C doesn't initialize automatic (local) variables, mystring has an undefined value. It can point to any random part of memory. When you try to gets using this memory location, you're trying to write to that memory that doesn't belong to you.
Finally, this condition with a single =: else if (mystring = '\0') is an assignment, and not an equality test.

C segmentation fault errors with feof() and fgetc()

Can anyone help me solve my dilemma? When I compile my program I get no errors or warnings. When I go to actually run the executable, though, I get a segmentation error. If I'm to understand correctly, this happens because a pointer is in short being used incorrectly. I get a specific error on the feof(srcIn) line and I'm not sure why. The FILE* srcIn is never assigned a new value aside from the srcIn = fopen(argv[0], "r") value at the beginning of the program. I had originally had this solution implemented in C++ and needed to changed it to C for reasons. Anyways, in the C++ one I did essentially the same exact thing except using srcIn.eof() as the the condition and srcIn.get(something) as the reading method. and it compiled and ran without any problems.
int chara;
int line[maxLineLength+1];
void nextch(void){
const int charPerTab = 8;
if(charCounter == charLineCounter){
if(feof(srcIn)){
printf("\n");
isEOF = TRUE;
return;
}
printf("\n"); lineCounter++;
if(chara != '\0'){ printf("%c", line[charLineCounter-1]); } // first character each line after the first line will be skipped otherwise
charLineCounter = 0; charCounter = 0;
while(chara != '\n'){
chara = fgetc(srcIn);
if(chara >= ' '){
printf("%c", chara);
line[charLineCounter] = chara; charLineCounter++;
}
else if(chara == '\t'){ // add blanks to next tab
do{ printf(" "); line[charLineCounter] = ' '; charLineCounter++; }
while(charLineCounter % charPerTab != 1);
}
}
printf("\n"); line[charLineCounter] = chara; charLineCounter++; line[charLineCounter] = fgetc(srcIn); charLineCounter++;
// have to get the next character otherwise it will be skipped
}
chara = line[charCounter]; charCounter++;
}
EDIT:
I forgot to mention that I'm not even actually going into main when I get the seg fault. This leads me to believe that the executable itself has some sort of problem. gdb tells me the seg fault is happening at line:
if(feof(srcIn))
Any ideas?
I've got a haunting suspicion that your two-or-four-character indents aren't sufficient to let you see the real scope of the program; it could be as easy as #mu is too short and #Null Set point out, that you've got an argv[0] when you meant argv[1], and it could be as #Lou Franco points out and you're writing past the end of your array, but this code sure smells funny. Here's your code, run through Lindent to get larger tabs and one-statement-per-line:
int chara;
int line[maxLineLength + 1];
void nextch(void)
{
const int charPerTab = 8;
if (charCounter == charLineCounter) {
if (feof(srcIn)) {
printf("\n");
isEOF = TRUE;
return;
}
printf("\n");
lineCounter++;
if (chara != '\0') {
printf("%c", line[charLineCounter - 1]);
} // first character each line after the first line will be skipped otherwise
charLineCounter = 0;
charCounter = 0;
while (chara != '\n') {
chara = fgetc(srcIn);
if (chara >= ' ') {
printf("%c", chara);
line[charLineCounter] = chara;
charLineCounter++;
} else if (chara == '\t') { // add blanks to next tab
do {
printf(" ");
line[charLineCounter] = ' ';
charLineCounter++;
}
while (charLineCounter % charPerTab != 1);
}
}
printf("\n");
line[charLineCounter] = chara;
charLineCounter++;
line[charLineCounter] = fgetc(srcIn);
charLineCounter++;
// have to get the next character otherwise it will be skipped
}
chara = line[charCounter];
charCounter++;
}
You're checking whether or not you've read to the end of the file at the top, in an if statement, but you never check for eof again. Never. When you read from input in your while() loop, you use '\n' as your exit condition, print the output if the character is above ' ', do some tab expansion if you read a '\t', and you forgot to handle the EOF return from fgetc(3). If your input file doesn't have an '\n', then this program will probably write -1 into your line array until you segfault. If your input file does not end directly on a '\n', this program will probably write -1 into your line array until you segfault.
Most loops that read one character from an input stream and operate on it are written like this:
int c;
FILE *f = fopen("foo", "r");
if (!f) {
/* error message if appropriate */
return;
}
while ((c=fgetc(f)) != EOF) {
if (' ' < c) {
putchar(c);
line[counter++] = c;
} else if ('\t' == c) {
/* complex tab code */
} else if ('\n' == c) {
putchar('\n');
line[counter++] = c;
}
}
Check the input for EOF. Read input from only one spot, if you can. Use one table or if/else if/else if/else tree to decide what to do with your input character. It might not come natural to use the array[index++] = value; idiom at first, but it is common in C.
Feel free to steal my suggested loop format for your own code, and pop in the complex tab expansion code. It looked like you got that right, but I'm not positive on that, and I didn't want it to distract from the overall style of the loop. I think you'll find extending my code to solve your problem is easier than making yours work. (I fully expect you can, but I don't think it'd be fun to maintain.)
argv[0] is the name of your program so your fopen(argv[0], 'r') is probably failing. I'd guess that you want to open argv[1] instead. And, of course, check that the fopen succeeds before trying to use its return value.
It should probably be srcIn = fopen(argv[1], "r") instead. The 0th string parameter your main gets is normally the name of the program, and the 1st parameter is the first command line paramter you passed to the program.
It might not be in this function, but if the problem is here, I'd be most suspect of going out of bounds on line. Are you ever writing more than maxLineLength characters? You should put a check before you ever index into line.
Edit: You seem to be confused about what this error even means -- I will try to clear it up.
When you get a segmentation fault, the line that it happens on is just the line of code where it was finally detected that you have corrupted memory. It doesn't necessarily have anything to do with the real problem. What you need to do is to figure out where the corruption happened in the first place.
Very common causes:
calling free or delete on a pointer more than once
calling the wrong delete on a pointer (delete or delete[])
using an uninitialized pointer
using a pointer after free or delete was called on it
going out of bounds of an array (this is what I think you did)
casting a pointer to a wrong type
doing a reinterpret_cast where the target type cannot be reinterpreted correctly
calling functions with improper calling conventions
keeping a pointer to a temporary object
And there are many other ways.
The key to figuring this out is to
assume that your code is wrong
look for these kinds of problems by inspection in the code path (if short)
use tools that can tell you that you have these problems at the line of code where you did it
realizing that the line of code where the segmentation fault happens is not necessarily the bug.

Resources