I'm writing an application which should read some data at some level from a file. When I run the code (including fopen() and fclose())for more than a few hundred times, I got the error message (which I know it means that it cannot open the file):
Debug Assertaion Failed!
Program:
D:\blahblah
file: f:\dd\vctools\crt\crtwin32\stdio\fgets.c
Line: 57
Expression: (string!=NULL)
Can you please help me to understand why it should break after more than three hundered time?
Func_Main(char * filePath, ...){
for(int i=0;i<1000;i++){
Func_1(filePath);
....
}
....
}
Func_1(char* filepath){
char buffer[1024];
FILE * file= NULL;
file = fopen(filepath, "r");
while(fgets(buffer, sizeof(buffer), file)){
\\ do something
}
fclose(file);
}
You should check the return value of fopen. It will return a null pointer if opening the file failed.
And it will fail because \ is an escape character , use \\ in the filename string.
Problems I see:
You never use the argument passed to Func_1. You use a hard coded path instead.
The hard coded path has an error. You are not escaping the backslash in the hard coded path . It should be:
file = fopen("c:\\blahblah.txt", "r");
^^
You are not checking whether fopen was successful. You are assuming it was successful. Use:
file = fopen("c:\\blahblah.txt", "r");
if ( file == NULL )
{
// Deal with the error.
perror("Unable to open the file");
}
Update, after the OP edited the question
The first two points can be ignored. The last point still needs to be considered.
file = fopen(filepath, "r");
if ( file == NULL )
{
// Deal with the error.
perror("Unable to open the file");
}
Related
I am writing a program that reads from a file passed as an arguement, or reads from stdin if no arguements are given.
The code runs fine with a file passed, but I get a seg fault when no file is passed.
I basically call fopen on argv[1] if a file was given, but if no file was given I call:
f = fopen("stdin", "r");
Is this the correct syntax for opening stdin as a file?
When you start a program, the main() function is not the first thing that
get's called, quite a few things happen before the main() function is
called. One of those things is to open stdin, stdout and stderr. In
general you don't need to worry about the details how the OS does that, you
just can relay that when main() is executed, these streams are open and you
can use them.
So in your case, you can do this:
#include <stdio.h>
int main(int args, char **argv) {
FILE *fp;
if(args == 1) {
fp = stdin;
} else {
fp = fopen(argv[1], "r");
if(fp == NULL) {
fprintf(stderr, "Unable to open %s for writing\n", argv[1]);
return 1;
}
}
// do your read operations on fp
if(fp != stdin) {
fclose(fp);
}
return 0;
}
So when you call the program without arguments, stdin is used, otherwise a
file is used.
The reason why your code crashes is because
f = fopen("stdin", "r");
tries to open a file literally called stdin, which you most probably don't
have. fopen will return NULL and you probably don't check for that. If you
try to use a function that expects a FILE* pointer but pass NULL, then
you'll most likely will get a segfault.
USE f = stdin;
NOT f = fopen("stdin", "r");
I'm writing a simple code on Linux that writes into a file. That file will be stored in specific path ( not the same path where the executable is located ).The problem is that when I execute the code , the program is terminating with segmentation fault (core dump)
Here is my code :
#include <stdio.h>
int main ()
{
FILE * pFile;
char buffer[] = { 'x' , 'y' , 'z' };
pFile = fopen ("/home/medwajih/Desktop/bufferfile/buffer.txt", "wb");
fwrite (buffer , sizeof(char), sizeof(buffer), pFile);
fclose (pFile);
return 0;
}
Note that the exe of the program is in "/home/medwajih/Desktop/" and the location where I want to create the buffer.txt file is "/home/medwajih/Desktop/bufferfile/"
Thank you.
If the fopen fails (such as if the /home/medwajih/Desktop/bufferfile directory does not exist, or the file exists but has permissions that disallow you replacing it), then pFile will be set to NULL.
Attempting to use it is then undefined behaviour.
You should generally check all calls that may fail to ensure they don't cause issues later on, such as with:
pFile = fopen ("/home/medwajih/Desktop/bufferfile/buffer.txt", "wb");
if (pFile == NULL) {
fprintf (stderr, "Could not create file\n");
return 1;
}
If the problem is actually that the directory does not exist, you can call mkdir beforehand. And, of course, check the return value of that as well :-)
If it's something else (there's not really enough information in the question to ascertain what it is), you need to find a different way to rectify the problem.
The following is my code for a method that copies a file from a path to a file to a directory provided as the destination. The copy works perfectly fine, however my chmod call assigns the wrong permissions to the copied file in the destination. If the permission in the source is 644, the copied file has a permission of 170 or 120.
I have been attempting to debug this for hours and it's driving me slightly crazy so any help is greatly appreciated.
void copy_file(char* src, char* dest) {
char a;
//extract file name through a duplicate ptr
char* fname = strdup(src);
char* dname = basename(fname);
//open read and write streams
FILE* read;
FILE* write;
read = fopen(src, "r");
chdir(dest);
write = fopen(dname, "w");
//error checking
if (read == NULL) //|| (write == NULL))
{
perror("Read Error: ");
exit(0);
}
else if (write == NULL)
{
perror("Write Error: ");
exit(0);
}
//write from src to dest char by char
while (1){
a = fgetc(read);
if (a == EOF)
{
break;
}
fputc(a, write);
}
//close files
fclose(read);
fclose(write);
// this is where I attempt to assign source file permissions
//and it goes horribly wrong
struct stat src_st;
if(stat(src, &src_st)){
perror("stat: ");
}
chmod(dname, src_st.st_mode);
printf("%o\n", src_st.st_mode & 0777);
}
You fopen(src, "r"), then you chdir(dest). This means that when you later call stat(src, &src_st), there is no reason to think that stat will access the same file as fopen did, or indeed that stat will access any file at all.
If stat fails, you proceed to call chmod anyway, so you pass whatever random junk was in src_st.st_mode to chmod.
You should use fstat(fileno(read), &src_st) before calling fclose(src), instead of calling stat(src, &src_st).
The basic problem is you have to check your system calls like fopen, chdir, and stat immediately.
For example, first thing I tried was copy_file( "test.data", "test2.data" ) not realizing it expected a destination directory.
char* fname = strdup(src);
char* dname = basename(fname);
dname is now test.data, same as the source.
read = fopen(src, "r"); // succeeds
chdir(dest); // fails
write = fopen(dname, "w"); // blows away test.data, the source
You do eventually check read and write, but after the damage has been done.
Blowing away your source file is really bad. It's important that your code deals with failed system calls. If you don't, it will sail along causing confusion and destruction.
Most system calls in C return 0 for success. This is an anti-pattern where the return value is an error flag, so false is failure, and anything else indicates what kind of error (though stat doesn't use that, it uses errno).
When it fails, stat returns -1 which is true. So this is the wrong way around.
struct stat src_st;
if(stat(src, &src_st)){
perror("stat: ");
}
Instead, you have to check for non-zero.
struct stat src_st;
if(stat(src, &src_st) != 0 ){
// Note that I don't use perror, it doesn't provide enough information.
fprintf(stderr, "Could not stat %s: %s\n", src, strerror(errno));
exit(1);
}
As you can guess this gets tedious in the extreme, and you're going to forget, or do it slightly different each time. You'll want to write wrappers around those functions to do the error handling for you.
FILE *fopen_checked( const char *file, const char *mode ) {
FILE *fp = fopen(file, mode);
if( file == NULL ) {
fprintf(stderr, "Could not open '%s' for '%s': %s", file, mode, strerror(errno));
exit(1);
}
return fp;
}
It's not the best error handling, but it will at least ensure your code appropriately halts and catches fire.
A note about chdir: if you can avoid it don't use it. chdir affects the global state of the program, the current working directory, and globals add complexity to everything. It's very, very easy for a function to change directory and not change back, as yours does. Now your process is in a weird state.
For example, if one did copy_file( "somefile", "foo" ) this leaves the program in foo/. If they then did copy_file( "otherfile", "foo" ) they'd be trying to copy foo/otherfile to foo/foo/otherfile.
And, as #robmayoff pointed out, your stat fails because the process is now in a different directory. So even the function doing the chdir is confused by it.
Ensuring that your functions always chdir back to the original directory in a language like C is very difficult and greatly complicates error handling. Instead, stay in your original directory and use functions like basename to join paths together.
Finally, avoid mixing your file operations. Use filenames or use file descriptors, but try not to use both. That means if you're using fopen, use fstat and fchmod. You might have to use fileno to get a file descriptor out of the FILE pointer.
This avoids having to carry around and keep in sync two pieces of data, the file descriptor and the filename. It also avoids issues with chdir or the file being renamed or even deleted, the file descriptor will still work so long as it remains open.
This is also a problem:
char a;
...
while (1){
a = fgetc(read);
if (a == EOF)
{
break;
}
fputc(a, write);
}
fgetc() returns int, not char. Per the C Standard, 7.21.7.1 The fgetc function:
7.21.7.1 The fgetc function
Synopsis
#include <stdio.h>
int fgetc(FILE *stream);
Assuming sizeof( int ) > sizeof( char ), char values are signed, 2s-complement integers, and EOF is an int defined to be -1 (all very common values), reading a file with char a = fgetc( stream ); will fail upon reading a valid 0xFF character value. And if your implementation's default char value is unsigned char, char a = fgetc( stream ); will never produce a value that matches EOF.
I am working through the excellent The C Programming Language at the moment, and have got stuck while trying to open and read a file. The program compiles, but seg faults on execution:
$ ./a.out
Segmentation fault
Here is the code:
#include <stdio.h>
main()
{
FILE *fp;
fp=fopen("/home/c-sandbox/index.html", "r");
fprintf(fp, "Testing...\n");
fclose(fp);
}
Note that the path points to a real file containing the string "hello, world".
Any ideas on where I am going wrong?
Make sure fp is not NULL before trying to write to it. For example:
if(fp == NULL)
{
fprintf(stderr, "Cannot open file\n");
return EXIT_FAILURE; // defined in stdlib.h
}
You need to open the file with something other than "r", which only allows file reading. Read the man page for fopen to find out which mode would work the best for you. Example:
"w" - Truncate to zero length or create file for writing.
"a" - Append; open or create file for writing at end-of-file.
You opened the file for reading only, and are attempting to write to it.
Use "a" if you want to append to the end of the existing file.
Edit: As others have noted, you're also not checking to see if the file was opened. fopen will return NULL if it fails and set the global variable errno to a value that indicates why it failed. You can get a human-readable explanation using strerror(errno)
if( fp == NULL ) {
printf( "Error opening file: %s\n", strerror( errno ) );
}
You are opening it in readonly mode! Need to use w or a for writing/appending to the file :)
fopen("/home/c-sandbox/index.html", "w");
You should check that fopen does not return NULL. I suspect it is returning NULL and either the fprintf and/or fclose calls are getting messed up.
#include <stdio.h>
main()
{
FILE *fp;
fp=fopen("/home/c-sandbox/index.html", "r");
if(!fp)
{
perror ("The following error occurred");
return ;
}
fgets(line,len,fp);
printf("%s",line);
fclose(fp);
fp=fopen("/home/c-sandbox/index.html", "a");
if(!fp)
{
perror ("The following error occurred");
return ;
}
fprintf(fp, "Testing...\n");
fclose(fp)
}
for reading "hello, world" string present in file.
after reading write to the same file "Testing..."
I'm working on a simple file splitter/merger program in the C programming language. The problem is, for some reason fopen returns NULL, and because of that, my program is crashing at the fwrite statement. How do I fix this?
Here is the C file:
int SplitFile(char* filename, char* output, size_t size)
{
char current_file_name[256];
int file_count = 0, i = 0;
FILE *file = fopen( filename, "rb" );
printf("split %s into chunks of %d named\n", filename, size);
if (!file)
return E_BAD_SOURCE;
else
{
output = (char *) malloc(size * sizeof(char));
if (output == NULL)
return E_NO_MEMORY;
else
{
int bytes_read = 0;
FILE *outFile;
do
{
bytes_read = fread(output, sizeof(char), size, file );
sprintf(current_file_name, "%s%04lu\n", "part", file_count++);
outFile = fopen (current_file_name, "wb" ); // THIS RETURNS NULL
fwrite(output, sizeof(char), bytes_read, outFile); //CRASHES ON THIS LINE
}
while ( bytes_read > 0 )
;
//fclose(outFile);
}
}
fclose(file);
printf("...\n");
return 0;
}
The proper thing to do is check errno when fopen returns NULL.
I'm going to guess that your problem is that you're trying to write to a filesystem that doesn't allow \n in filenames, but it could be a permissions issue as well.
There are many reasons fopen can return NULL including (but certainly not limited to):
The file doesn't exist
The file is opened in a mode that doesn't allow other accesses
The network is down
The file exists, but you don't have permissions
A file exists with the name you gave, but the current directory of the process is not what you expected so the relative pathname fails to find and open the file.
The way to find out which is responsible is to dig into the errno code.
However just because you resolve this particular error doesn't mean you can assume fopen will never return NULL. When dealing with I/O operations your code simply has to expect failure. It's not possible to predict the success of I/O operations, and they can always fail.
It means that the file might not exist or some permission error occurred while accessing a file such as "Read-Only" or "Write-Protected", so in those cases fopen will return 0 (a NULL pointer). On success it will return a file pointer as a handler.
fp=fopen("c:\\ABC.txt", "r"); cannot be the same as fp=fopen("c:\\abc.txt", "r");.
Use // instead of \\ in a Linux environment.
P.S.: In Linux and Unix-like operating systems file names are case-sensitive.
Is fopen for write return NULL in the first run?
I noticed that in the while you keep open files for write but not closing them.
Try to add fclose(outFile) after fwrite:
outFile = fopen ( current_file_name , "wb" );
fwrite(output, sizeof( char ), bytes_read, outFile);
fclose(outFile)
It is possible you open more files than your OS allows.
In Unix, for fopen(), there is no reason to prepend ./ to a filename passed to fopen().
In my case, i was reading the same file all over again in a while loop and forgot to close it.
I used a function for reading the file and finding a match and the function had a return; statement that terminated the function before doing fclose(fp) :D
The path given for the file is checked from wherever the executable is present.
In my case I was opening the text file in c file when both were present at the same place.
It was continuously giving the error of file not found.
Placed the file in the folder of executable and it started working.
In my case, it was because I was trying to create the file in a directory that does NOT exist.