2019独角兽企业重金招聘Python工程师标准>>>

fopen函数的使用

在定义FILE * fp 之后,fopen的用法是: fp = fopen(filename,"w")。而对于fopen_s来说,还得定义另外一个变量errno_t err,然后err = fopen_s(&fp,filename,"w"),注意第一个参数是指向FILE*的指针,即二重指针。返回值的话,对于fopen来说,打开文件成功的话返回文件指针(赋值给fp),打开失败则返回NULL值;对于fopen_s来说,打开文件成功返回0,失败返回非0。

在vs编程中,经常会有这样的警告:warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use_CRT_SECURE_NO_WARNINGS. See online help for details.  是因为 fopen_s比fopen多了溢出检测(question:什么地方用了溢出检测,这里也没有像gets_s???),更安全一些。(在以后的文章里还有get与get_s的比较,strcpy strcpy_s的比较,他们的共同点都是用来一些不可预料的行为,以后将进行详尽解释)

Closes a stream (fclose) or closes all open streams (_fcloseall).

int fclose( FILE *stream );

int _fcloseall( void );

Function    Required Header   Compatibility

fclose
<stdio.h>
ANSI, Win 95, Win NT

_fcloseall
<stdio.h>
ANSI, Win 95, Win NT

For additional compatibility information, see Compatibility in the Introduction.

Libraries

LIBC.LIB
Single thread static library, retail version

LIBCMT.LIB
Multithread static library, retail version

MSVCRT.LIB
Import library for MSVCRT.DLL, retail version

Return Value

fclose returns 0 if the stream is successfully closed. _fcloseall returns the total number of streams closed. Both functions return EOF to indicate an error.

Parameter

stream

Pointer to FILE structure

Remarks

The fclose function closes stream. _fcloseall closes all open streams except stdin, stdout, stderr (and, in MS-DOS®, _stdaux and _stdprn). It also closes and deletes any temporary files created by tmpfile. In both functions, all buffers associated with the stream are flushed prior to closing(note:所有的与这些流相关联的缓冲区都在这些流被关闭前被刷新,从而保证不会因为关闭而丢失数据). System-allocated buffers are released when the stream is closed. Buffers assigned by the user with setbuf and setvbuf are not automatically released.(ASK:setbuf和setvbuf这两个函数有什么作用呢?)

Example

/* FOPEN.C: This program opens files named "data"* and "data2".It  uses fclose to close "data" and* _fcloseall to close all remaining files.*/
#include <stdio.h>FILE *stream, *stream2;int main(void){    int numclosed;    errno_t err;    // Open for read (will fail if file "crt_fopen_s.c" does not exist)    if ((err = fopen_s(&stream, "crt_fopen_s.c", "r")) != 0)        printf("The file 'crt_fopen_s.c' was not opened\n");    else        printf("The file 'crt_fopen_s.c' was opened\n");    // Open for write     if ((err = fopen_s(&stream2, "data2", "w+")) != 0)        printf("The file 'data2' was not opened\n");    else        printf("The file 'data2' was opened\n");    // Close stream if it is not NULL     if (stream)    {        if (fclose(stream))        {            printf("The file 'crt_fopen_s.c' was not closed\n");        }    }    // All other files are closed:    numclosed = _fcloseall();    printf("Number of files closed by _fcloseall: %u\n", numclosed);}

Output

================

_s类函数的使用策略

首先介绍下gets_s、getws_s函数的用法。gets_s, _getws_s
https://msdn.microsoft.com/en-us/library/5b5x9wc7.aspx

Gets a line from the stdin stream. These versions of gets, _getws have security enhancements(安全加强), as described in Security Features in the CRT.

char *gets_s(
   char *buffer,
   size_t sizeInCharacters
);
wchar_t *_getws_s(
   wchar_t *buffer,
   size_t sizeInCharacters
);
template <size_t size>
char *gets_s(
   char (&buffer)[size]
); // C++ only
template <size_t size>
wchar_t *_getws_s(
   wchar_t (&buffer)[size]
); // C++ only

Parameters

[out] buffer

Storage location for input string.

[in] sizeInCharacters

The size of the buffer.

Return Value

Returns buffer if successful. A NULL pointer indicates an error or end-of-file condition. Use ferror or feof to determine which one has occurred.

Remarks

The gets_s function reads a line from the standard input stream stdin and stores it in buffer. The line consists of all characters up to and including the first newline character ('\n'). gets_s then replaces the newline character with a null character ('\0') before returning the line. In contrast, the fgets_s function retains the newline character.

If the first character read is the end-of-file character, a null character is stored at the beginning of buffer and NULL is returned.

_getws is a wide-character version of gets_s; its argument and return value are wide-character strings.

If buffer is NULL or sizeInCharacters is less than or equal to zero, or if the buffer is too small to contain the input line and null terminator, these functions invoke an invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions return NULL and set errno to ERANGE.

In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure Template Overloads.

顺便说一下,scanf与scanf_s、gets与gets_s(note:这里的gets_s里的第一个s表示string即字符串,第二个表示safe)、以及这里的fopen_s和fopen,之所以说带_s的函数安全,并不是说在在用户输入超过缓冲区长度时不报错,而是正好相反,在检测到缓冲区不够时,一定会报错。

From Security Features in the CRT   https://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx

The secure functions do not prevent or correct security errors; rather(而是), they catch errors when they occur. They perform additional checks for error conditions, and in the case of an error, they invoke an error handler (see Parameter Validation).

不会像scanf接收字符到一个char数组里,如果用户输入的字符数超过了缓冲区的长度时,scanf也可能“一声不吭”(注:在一些编译器下,确实会存在这种情况),这种做法在一段时间内可能不会产生什么异常,但是操作不属于自己的内存空间,这本身就是一个漏洞,即所谓的“缓冲区溢出漏洞”,经常被一些黑客利用。想想如果这些被误操作的字节,正好对应一个关键数据,或者是对应一个函数的入口地址(注:这种情况下,黑客可以利用缓冲区溢出漏洞将这个入口地址改为它自己编写的木马程序的入口地址。你就悲剧了!纯粹道听途说,自己没试过!!)

》》》可能有些同学对gets_s在接收到超过缓冲区长度的数据时的弹出错误或警告窗体的做法表示不解,其实我的心里是想让按下面方式行事。

一、当用户输入的数据的长度(注:到底指什么要搞清楚)不超过缓冲区长度时,正常接收换行符前的所有字符。

(note:如果不注意的话,这里又是一个pitfall,当然前提是你在使用gets_s时,输入中既有中文,又有英文等西方字符,后面写一篇关于接收单字节字符和宽字符的区别的日志。对于实用程序应该始终使用w_char)。

二、当用户的输入的数据的长度超过缓冲区长度时,接收“第二个参数的值减一”个字符,并将缓冲区最后一个字符设置为终止符。(ASK:宽字符中的终止符是什么样的?两个字节的全0吗?)。

对于我们的第二条愿望,标准库中的默认实现一般会是报错提醒,但是真正的实用的应用程序,用户不会允许自己使用的软件动不动就报错,暂且不讨论有多少用户会使用从控制台接收输入的软件。实际上这也是可以实现的。

From Parameter Validation https://msdn.microsoft.com/en-us/library/ksazx244.aspx

Most of the security-enhanced CRT(C运行时) functions and many of the preexisting(先前存在的) functions validate their parameters. This could include checking pointers for NULL, checking that integers fall into a valid range, or checking that enumeration values are valid. When an invalid parameter is found, the invalid parameter handler is executed.
note:注意这时提到一些验证参数的例子,翻译如下:
一、指针是否为空。
二、整型是否会落入一个有效的范围。
三、检查枚举类型是否有效。
而且如果一个无效的参数被发现,会执行相应的无效参数处理机制。???是每一种类型的参数异常对应一种处理机制吗?

Invalid Parameter Handler Routine
--------------------------------------------------------------------------------
The behavior of the C Runtime when an invalid parameter is found is to call the currently assigned invalid parameter handler. The default(note:这里应该指的是运行时,而不是调试时) invalid parameter invokes Watson crash reporting, which causes the application to crash and asks the user if they want to load the crash dump to Microsoft for analysis. In Debug mode, an invalid parameter also results in a failed assertion.如下图所示,是gets_s函数接收的用户输入超过缓冲区长度时的警告窗口。

This behavior can be changed by using the function _set_invalid_parameter_handler to set the invalid parameter handler to your own function.(note:你可以通过set_invalid_parameter_handler 函数来设定无效参数 的处理机制到你自己定义的函数) If the function you specify does not terminate the application, control is returned to the function that received the invalid parameters, and these functions will normally cease execution, return an error code(note:这个收到无效参数的函数会正常地结束执行,并返回一个错误码。注意反省一下,自己在处理相应的问题时,对于非法输入是都能返回相应的错误码。ASK:在编程时如何利用函数返回值和errno值????), and set errno to an error code. In many cases, the errno value and the return value are both EINVAL, indicating an invalid parameter. In some cases, a more specific error code is returned, such as EBADF for a bad file pointer passed in as a parameter. For more information on errno, see errno, _doserrno, _sys_errlist, and _sys_nerr.
==========

转载于:https://my.oschina.net/ray1421/blog/704280

fopen,fopen_s,fclose, _fcloseall函数用法相关推荐

  1. C++文件操作——fopen/fseek/ftell/fread/fwrite/fclose等函数用法

    1. fopen FILE * fopen(const char * path,const char * mode); 函数说明 参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代 ...

  2. c语言中fopen_s函数,关于C语言中从文件读取数据时,fopen,fopen_s和fscanf,fscanf_s的函数用法(函数的用法有很大区别)...

    首先这都是针对由于VS软件的设置,一些函数的需要在函数名后面加"_s"才能使用. (或者最直接的方法程序开头加#pragma warning(disable:4996) 就什么问题 ...

  3. fclose在c语言中的作用,c语言fcloseall函数用法实例介绍

    c语言fcloseall函数用法实例介绍.fcloseall函数的返回值,函数 fcloseall() 将所有打开的流与其底层的文件或功能集合关闭.任何缓冲的数据都将首先被写入,使用 fflush(3 ...

  4. fopen()和fclose()的用法

    fopen()和fclose()的用法 1.fopen()函数的用法 fopen函数用于打开文件, 其调用格式为: FILE *fopen(char *filename, *type); fopen( ...

  5. php fopen创建文件,php fopen函数用法(打开创建文件)

    php教程 fopen函数用法(打开创建文件) 在很多时间我们都需要创建文件特别是生成静态页面的时间,我们在php中就常常会用到fopen这个函数来新建文件,它的原是是如何文件存在就追加,不存在可以创 ...

  6. fopen和fclose的用法

    fopen()和fclose()的用法1.fopen()函数的用法fopen函数用于打开文件, 其调用格式为:FILE *fopen(char *filename, *type);fopen()函数中 ...

  7. php fopen函数php,php fopen函数用法(打开创建文件)_PHP教程 - fopen

    php教程 fopen函数用法(打开创建文件) 在很多时间我们都需要创建文件特别是生成静态页面的时间,我们在php中就常常会用到fopen这个函数来新建文件,它的原是是如何文件存在就追加,不存在可以创 ...

  8. 文件操作之打开文件——fopen函数用法

    1.格式: FILE *fp: fp=fopen("filename.txt","r") 2.说明:第一行定义一个文件指针类型的变量fp.第二行打开一个文件, ...

  9. Linux下标准I/O库函数fopen、fclose函数的使用方法

    fopen.fclose使用方法详解 1.I/0的管理分类 1.1打开流 1.2关闭流 1.3代码实操 1.4运行截图 无论是编写系统程序还是应用程序,都离不开I/O这个重要的环节. 相对于低级的I/ ...

最新文章

  1. EasyStack 与F5合作, OpenStack开源云平台携手软件定义的应用交付服务
  2. spring jdbcTemplate使用queryForList示例
  3. mysql groupby 取值_mysql获取groupby总记录行数的方法
  4. 输出整数的位数、按位输出(两种)以及逆序输出
  5. 代理模式给我们带来的便利
  6. 【问题解决方案】Linux中进入目录下文件夹
  7. [转]Android核心分析之二:方法论探讨之概念空间篇
  8. Ext.widgets-menu
  9. [手把手教你] 用Swoft 搭建微服务(TCP RPC)
  10. 在线开票服务器设置,开票服务器系统介绍
  11. 整人代码好玩到没朋友
  12. 《工作五年,决定你一生的财富》读后感
  13. 微软苏州2018冬季实习面试经历
  14. 因果图法测试中国象棋马
  15. 创建新Docker容器时出现“The container name /xxx is already in use by container xxxxxxxxxxx...”问题的解决办法
  16. 淘宝详情页分发推荐算法总结:用户即时兴趣强化
  17. oracle exception others,Oracle PL/SQL之EXCEPTION -- WHEN OTHERS THEN
  18. Python地球科学领域应用:python处理遥感数据、站点数据、遥感水文数据、气候变化数据、WRF模式数据后处理、运行生态模型
  19. C语言——PTA 最大公约数和最小公倍数
  20. vue项目每30秒刷新1次接口获取数据

热门文章

  1. 360手机卫士界面布局学习过程续(一)
  2. Visual Studio 2010 重构XAML的一个bug
  3. 虚拟机安装Solaris10
  4. 3/5 MySQL入门总结:数据库(DATABASE)操作
  5. SQL性能优化工具TKPROF
  6. Oracle 生成随机密码
  7. Transact-SQL 示例 - 如何在拼接的动态sql内调用外部变量
  8. Linux 下使用Java连接 mysql
  9. vue 数组数据改变 视图不更新解决方案
  10. js判断最后一个字符是不是指定字符_结合简单的 JS 就可以让 CSS 也能做搜索