I have a problem with programming in C, especially with fopen in Visual Studio. I read about the fopen_s
function and added the following line to my project, but it still doesn't work.
_CRT_SECURE_NO_WARNINGS
So I tried using fopen_s
in this way:
FILE *fp;
errno_t err;
if ((err = fopen_s(&fp, "C:/File.txt", "rt")) != 0)
printf("File was not opened\n");
else
fprintf(fp, "Date: %s, Time: %s, Score: %i \n", __DATE__, __TIME__, score);
fclose(fp);
It's still crashing. What's wrong?
Save this answer. Show activity on this post. fopen_s is a variant of fopen which contains parameter validation and hands back an error code instead of a pointer in case something goes wrong during the open process. It's more secure than the base variant because it accounts for more edge conditions.
The fopen function opens the file that is specified by filename . By default, a narrow filename string is interpreted using the ANSI codepage ( CP_ACP ). In Windows Desktop applications, it can be changed to the OEM codepage ( CP_OEMCP ) by using the SetFileApisToOEM function.
You use fclose
with an invalid fp
value, even if opening failed. Add {}
around the else
branch, at least.
Many developers think it is generally a good idea to use braces everywhere, even with one statement inside them. It's so easy to make a mistake like this if you don't, even for experienced developers. So put them around the then branch too.
The _s
functions are unportable Microsoft inventions which, for the most part, duplicate functionality that already existed under a more portable name. Moreover, blindly changing from the non-_s
variant of a function to the _s
variant generally does not fix anything. (For instance, silently truncating a string is less disastrous than clobbering the stack but it is still misbehavior which may be exploitable.)
Your problem -- which is not affected by the difference between fopen
and fopen_s
-- is almost certainly that you are not bothering to check for errors properly. Here is how to check for errors properly:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
{
FILE *fp;
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 2;
}
fp = fopen(argv[1], "rb");
if (!fp) {
fprintf(stderr, "opening %s: %s\n", argv[1], strerror(errno)); // HERE
return 1;
}
// use 'fp' here...
return 0;
}
Notice how the line marked // HERE
prints both the exact string that was passed to fopen
and the result of strerror(errno)
. It is absolutely essential that you print both the arguments and strerror(errno)
whenever a system call fails. (Note: If you do wind up using one of the _s
functions that returns an error code rather than setting errno
, then you must pass the return value to strerror
instead.)
Change your program to do this and you will be able to figure out why it isn't working.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With