fopen,fopen_s,fclose, _fcloseall函数用法
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] bufferStorage location for input string.
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函数用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中信公司是国企还是私企 是国企
- 下一篇: 虚拟货币是什么