Weird segfault after open file? - c

I'm getting a seg fault when I try and print fname. Can someone explain why this is happening to me? Is it that I'm not allowed to write to a file, close it, and then read from a file? argv[2] is defined. I've tried with multiple different allocations.
int main(int argc, char *argv[]){
//Other stuff
char *rfile=calloc(1, 2049);
strcpy(rfile, argv[2]);
FILE *wfile;
wfile = fopen(argv[2], "w");
SaveIndexToFile(index, wfile, alpha); // This does a whole bunch of writing to a the file.
fclose(wfile);
//alpha is declared here, and works just fine.
RemakeIndex(rfile, alpha);
return 1;
}
int RemakeIndex(char *fname, WordList * alpha){
printf("%s", fname);
return 1;
}

You are not checking the return value of fopen. If the fopen fails it can
return NULL. If you are doing something with NULL that can undefined behavior. Place this line after opening the file.
if ( wfile == NULL ){
perror("fopen");
return;
}
And check whether the argc count is three. If you are not giving arguments to the ./a.out then accessing the argv[2] can also lead to segmentation fault.

Is it that I'm not allowed to write to a file, close it, and then read from a file?
Yes, you are not allowed to read from a file [stream] after it had been closed.
Note on the (OP's) wording:
char * rfile is called a "pointer to char".
FILE * is called a "file-pointer" (or also just "pointer to FILE) or commonly (but formally wrong) just "file".
Also RemakeIndex() is called in main() without proper protoyping.
To fix this
either add a prototype before main():
int RemakeIndex(char *, WordList *);
or move the whole implementation of RemakeIndex() before main().
Also the printf() calls' output might not show up immediately on the console, as stdout is line buffered.
To fix this
either print out a trailing new-line:
printf("%s\n", fname);
or printf to stderr, which itself isn't line bufferd by default:
fprintf(strerr, "%s\n", fname);
or flush stdout after having printed to it:
printf("%s\n", fname);
fflush(stdout);

Prototyping the function is very important, the GCC compiler will assume an implicitly declared function (RemakeIndex in your code) has two arguments which are both int, which would make your code look like this:
int RemakeIndex(int fname, int alpha) {
printf("%s", (char *)fname);
return 1;
}
On a 64 bit machine and with GCC where pointers are 64 bits and ints are 32 bits then your arguments will be truncated to 32 bits which is likely to cause a segfault. The other answers have mentioned prototyping the function and if you are using a 64bit compiler I would suggest that this is your problem.

It ended up being that I was allocating way too much memory on the heap. I had a loop that was allocating strings of max_length of an unsigned int. Thank you for all of your comments and help!

Related

Fgets about the third parameter

I have this fragment
fseek(sp,f_line*fm,SEEK_SET);
fgets(buffer,LEN,(FILE*)sp);
I don't understand this part
(FILE)sp
I try to fill a char array with data from a file.
Apparently, someone thinks they are storing a file pointer in a variable sp that is not of type FILE *, so it is reputed to be necessary to cast the type to FILE *. See the POSIX definition of fgets(), which is meant to be equivalent to the standard C definition of the function.
However, given that the prior line calls fseek() with an uncast sp, and fseek() also expects a FILE *, someone is confused — the person writing the cast is confused.
The cast should be removed from the call to fgets().
Or, possibly but implausibly, the cast should be added to the call to fseek().
One outré possibility is that the user defined void *sp and used that to store the FILE * returned by fopen() or equivalent. Such a decision would be extremely unorthodox, and pointlessly opens up the code to type confusion, but could actually allow the code shown below to compile and run — but the cast is still unnecessary.
/* Abominable code - do not use! */
#include <stdio.h>
int main(void)
{
void *sp = fopen("abuse47.c", "r"); // The abomination!
if (sp != 0)
{
char buffer[256];
fseek(sp, 120, SEEK_SET);
if (fgets(buffer, sizeof(buffer), sp) != 0)
printf("[%s]\n", buffer);
fclose(sp);
}
return 0;
}

Segmentation Fault after reading a file into a struct array

I am trying to write a program that reads data from a file and puts it into a struct array. I have succeeded in putting it into the array but I then get a segmentation fault. I believe I have to use malloc to initialize the struct array but I am new to programming and don't really understand how to do this. Thanks for your help! I have copied pieces of my code so you can see what I've done. I have not included my functions in this code.
struct Weather
{
char location;
int daynum;
double temp;
double precip;
};
int main (void)
{
FILE*openFile;
char buffer[COLS][ROWS];
int i = 0;
struct Weather loc1; //initialize here?
for (i = 0; i <200; i++)
{
fgets (buffer[i], ROWS, openFile);
parseLine(buffer[i], &loc1);
printf ("%d %c %d %.2lf %.2lf\n",i, loc1.location, loc1.daynum, loc1.temp, loc1.precip);
}
}
Your file stream (openFile) is not initialized; it does not actually point to a file. As yano said in his comment, use fopen() in order to properly initialize the file pointer.
You must initialize the file stream with fopen() before any I/O operations!
int main()
{
char filename[64];
FILE *fp;
snprintf(filename, sizeof(filename), "hello1234.txt");
if(NULL == (fp = fopen(filename, "r")))
{
printf("err, failed when fopen(), %s %s[%d].\n", __FILE__, __FUNCTION__, __LINE__);
return -1;
}
//your code here
return 0;
}
Initialize the struct
Note that malloc() cannot initialize the struct.
two methods:
M0:
struct Weather loc1;
memset(&loc1, 0, sizeof(struct Weather));
M1:
struct Weather loc1 = {0};
man malloc or click the link for a malloc manual.
Multiple problems in your code:
The stream pointer openFile is uninitialized, calling fgets() for it invokes undefined behavior. You want to open a file for fopen() or set the value of openFile to the standard input stream stdin.
The 2D char array should be defined in the other order:
char buffer[ROWS][COLS];
you should use the same constant for the loop counter and the 2D array definition: ROWS might be defined to something less than 200.
the size of the line buffer is COLS, pass that to fgets().
you should test the return value of fgets(): it returns NULL at end of file and the contents of the destination array is indeterminate in this case.
whether or not to initialize loc1 depends on what the parseLine() function does. It would make sense that parseLine() make no assumptions about the contents of the destination structure, but the source has not been posted, so we cannot know for sure.
the printf format specifier for type double is %f, the extra l is simply ignored.

Having trouble with file I/O and string arrays

The file I'm reading from just has names separated by a line. What happens is the program tries to print the contents of line_array, and it will print out about 20 of the last line in the txt file.
#include <stdio.h>
FILE* fp;
int main(){
char* line;
const char* line_array[255];
int i= 0;
int b =0;
fp = fopen("noob.txt","r");
while(fgets(line,255,fp)){
line_array[i]=line;
printf("%s",line);
printf("%s",line_array[i]);
i++;
}
for(;b<i;b++){
printf("%s",line_array[b]);
}
fclose(fp);
return 0;
}
The first issue, in your code,
while(fgets(line,255,fp))
line is used uninitialized. There is no memory allocated to line. It invokes undefined behavior.
Then, you did not check for the success of fopen() before using the returned file pointer. Again, possible UB.
And finally, by saying
line_array[i]=line;
what you did is to store the line itself to all the occurrences of line_array[n], so for the later printf() loop, the latest content of line is being printed over and over again.
Solution(s):
Allocate memory to line or use a fixed length-array.
Check for the success of fopen()before using the returned pointer.
Allocate memory to each line_array[n] and use strcpy() to copy the content. Ottherwise, you can directly use strdup(), too.

C program just exits after trying to write to stdout

so written a small function (part of a larger program) and when i run it and input "GET" it exits with a value of 1. to be honest i'm still grasping the concept of open read and write to stdout but not sure what i've done wrong here.
int input_arg()
{
MainStruct val; //variables are loaded from a config file to this structure
char *getInput;
char *fileInput;
FILE *loadfile;
char buffer[1024];
int n;
int defaultFile = val.def; //success.txt value read when fileparser.c is run
printf("http >> :");
fflush(NULL);
fscanf(stdin,"%s", getInput);
if (getInput == "GET")
{
loadfile = fopen(defaultFile, "r");
if (loadfile == NULL)
{
fprintf(stderr, "error loading default resource: PROGRAM WILL EXIT");
exit(0);
}
while ((n = read(loadfile, buffer, sizeof(buffer))) > 0) //reads file (not sure this should be a while loop)
{
if((write(STDOUT_FILENO, buffer, n)) < 0) //writes to stdout
{
perror("failed to display file to output");
close(loadfile);
exit(1);
}
}
}
}
for compiling purposes the val.def pointer is a string as below
char defaultFile = "success.txt";
unsure of what i am missing here. tried changing the structure pointer to a simple char string to see if it was anything there but didn't actually make any difference. i think the problem is with the while loop...i don't think it should be there, but i have yet to find an example where a while loop ISN'T used in a write to stdout scenario.
thanks
It crashes because you have not allocated any memory for getInput to point at. So the program will crash when it attempts to follow the pointer, which will not point to anything useful.
Either allocate memory dynamically with for example malloc, or replace it with a static buffer.
Also, you may want to look at strcmp for comparing strings. Comparing strings in C with == will not compare the strings lexically, instead it will only compare the pointers pointing at them.
fscanf(stdin,"%s", getInput);
getInput is never initialized or allocated memory.Fix it by allocating memory
getInput = malloc(200);
Your program has serious issues, the most important one is that you are using fopen() with read() and that is wrong.
The read() function takes and int as first parameter, which is a file descriptor tha you can create via the open() function, and not fopen() which returns a FILE * object, so change[1]
FILE *loadFile;
to
int loadFile;
and
loadFile = fopen(defaultFile, "r");
to
loadFile = open(defaultFile, O_RDONLY);
and then to check for failure
if (loadFile == -1) /* it failed to open check errno? perhaps... */
you must enable compiler warnings to prevent this kind of mistake, because the first parameter of read() in your program is of incompatible type.
The fscanf() function expects a valid pointer for each "%s" specifier, you are passing an unintialzed pointer to it, dereferencing it inside of scanf() is undefined behavior.
You need to allocate space for it, something like this should work
char inputBuffer[100];
if (fscanf(stdin, "%99s", inputBuffer) != 1)
thereWasAProblemGettingInput_DoNotUse_inputBuffer_InTheCodeThatFollows();
Note that:
I used inputBuffer as a name for the variable, though this doesn't affect the program execution or compilation at all, the readability matters.
Used "%99s" to prevent buffer overflow.
Checked the value returned by fscanf() to make sure that the inputBuffer has valid data and was properly initialized.
String comparison in c is not like in many other languages, in your code
if (getInput == "GET")
is comparing the addresses of getInput and the string literal "GET", which will not be the same unless you make getInput point to "GET", since you want to compare the contents you need
if (strcmp(inputBuffer, "GET") == 0)
instead, and do not forget to include the string.h header.
[1]Note that loadFile is also a bad choice for a variable name, it feels like a function name, inputFile would be more appropriate.

"stack smashing detected" by getline & printf - and i really cant figure out why

when it comes to C i am not a noob - i'm more like a total & complete stupid ignorant noob! i am trying to write a program to parse simple text files, and i would like to make it as general as possible(why i use getline). well here is my code:
//afile.c
#include <stdio.h>
#include <stdlib.h>
main( )
{FILE *fp1;
char *filename;
char **line;
size_t *sz;
int s;
filename = "n";
if ((fp1 = fopen(filename,"r")) == NULL ){printf("error...");return 1;}
do {
s = getline(&line,sz,fp1);
if (s != -1)
printf(" %s \n",line);//<-- %s seems to be wrong! %*s removes the gcc warning
} while (s != EOF);
fclose(fp1);}
I am pretty sure its some pointer allocation problem, but i really cant figure out where it is. i've found out that replacing %s with %s makes the compiler warning disappear, but it results in an infinity of \t(tabs) being written in the terminal.
By the way, the error message i get is:
stack smashing detected *: ./afile terminated
Segmentation fault
getline expects an argument of type char**, and you supplied &line, which is char***. Additionally, getline acts on the current value of the value its first arguments points to (so, the value of line), and you didn't initialize it. Change your program to:
char *line = NULL;
and it should be fine.
You failed to initialize the line variable, and it contains a random value. Readline probably tries to realloc() it.
UPDATE: the definition for line is also wrong, only one asterix needed, as pointed out by others.
int main(void )
{
FILE *fp1;
char *filename;
char *line = NULL; /* <- here */
size_t *sz;
int s;
...
}
Your pointer redirections are inconsistent. The variable line is declared:
char **line;
Which is a pointer to a pointer to a character, or a pointer to a string. getline() expects a pointer to a string, but you pass &line - a pointer to a pointer to a string.
Finally, your printf() format specified is %s, do it wants to format a string, but you give it a pointer to a string.
Long story short: remove an asterisk to create
char *line;

Resources