protobuf无法使用open函数打开文件
说了一大堆就是说open函数在Windows下的在io.h头文件下,Linux下的在fcntl.h头文件下。同时若直接使用这个,则vs编译会提示error
C4996: 'open': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _open. See online help for details.
这是因为在vs下open函数已经被废弃,vs建议使用_open但使用_open又会出现error
C4996: '_open': This function or variable may be unsafe. Consider using _sopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
在工程设置里预编译头加上_CRT_SECURE_NO_WARNINGS即可不关心原因看到这里就结束了。
今天在使用protobuf做简单的参数存取时发现,Windows下无法使用open函数获取文件描述符
open 函数用于打开和创建文件。以下是 open 函数的简单描述
int open(const char *pathname, int oflag, ... );
于是查了下。
在Linux下open函数是在fcntl.h头文件中的(该头文件中包含了许多文件打开的模式定义和create、fcntl、open等函数),windows也有该头文件(但仅包含了一些文件打开模式的定义)。
Linux下fcntl.h内容:http://pubs.opengroup.org/onlinepubs/009695399/basedefs/fcntl.h.html
因此判定fcntl.h并不是标准库函数。查了下,果然如此(不得不说基础知识掌握不牢固啊)。
该头文件不属于标准库函数,且Windows下的fcntl.h头文件下没有该函数并不代表这个功能不能用,或者Windows下不能使用这个功能。毕竟protobuf就提供了这个接口。
查了写资料,有人说FILE结构体中包含了文件描述符这个字段,其形式如下(其中_file就是Linux下的文件描述符fd):
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file;//文件描述符 int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
但是我在VS2015下查找了下,发现其实现形式并非如此,而是这样:
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Stream I/O Declarations Required by this Header //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ typedef struct _iobuf { void* _Placeholder; } FILE;
因此认为应该是编译环境升级导致数据结构与原先发生了一些改变,无法使用(瞎猜的)。
后查阅资料发现vs下可用io.h头文件中的open函数实现获取文件描述符的功能。
C标准库
C标准库,顾名思义既然是标准,就是由标准组织制定的。
是由“美国国家标准协会(American National Standards Institute,ANSI)”为了规范C语言库而制定的标准。在最初,各个大学各个公司使用的C语言库都不尽相同,造成相互移植非常困难,在这个背景下,制定了这个标准。
下面是标准库函数的头文件:
标准头名 | 功能 | 描述 |
---|---|---|
<assert.h> | 诊断 |
仅包含assert 宏。可以在程序中使用该宏来诊断程序状态(例如某个变量是否为0等),若检查失败,程序终止。
|
<ctype.h> | 字符处理 | 包含判断字符类型及大小写转换的函数。 |
<errno.h> | 错误监测 |
提供了errno 。可以在调用特定库函数后检测errno 的值以判断调用过程中是否有错误发生。
|
<float.h> | 浮点数特性 | 提供了描述浮点数特性的宏。 |
<limits.h> | 整型特性 | 提供了描述整数类型和字符类型特性的宏。 |
<locale.h> | 本地化 | 提供了一些支持程序国际化的函数。 |
<math.h> | 数学计算 | 提供了大量用以数学计算的函数。 |
<setjmp.h> | 非本地跳转 |
提供了用于绕过正常的函数返回机制,从一个函数跳转到另一个正在活动的函数的setjmp 和longjmp 函数。
|
<signal.h> | 信号处理 | 提供了包括中断和运行时错误在内的异常情况处理函数。 |
<stdarg.h> | 不定参数 | 提供了支持函数处理不变个数的参数的工具。 |
<stddef.h> | 常用定义 | 提供了常用的类型和宏。 |
<stdio.h> | 输入输出 | 提供了大量输入输出函数。 |
<stdlib.h> | 常用实用函数 | 提供了大量实用的函数。 |
<string.h> | 字符串处理 | 提供了大量字符串处理函数。 |
<time.h> | 日期和时间 | 提供了获取、操纵和处理日期的函数。 |
C运行库
C运行库,是和平台相关的,即和操作系统相关的。
它由不同操作系统不同开发平台提供不同的C运行库。但是C运行库的部分实现是基于C标准库的,即C运行库是各个操作系统各个开发工具根据自身平台开发的库,某种程度上,可以说C运行库是C标准库的一个扩展库,只是加了很多C标准库所没有的与平台相关的或者不相关的库接口函数。举例子如:c标准库的strcpy函数负责字符串的拷贝,但是由于缺少对目地字符串缓冲区大小的控制,极有可能导致缓冲区溢出(大量的缓冲区溢出攻击都是由于这种漏洞而产生的);相反,Windows提供了能够实现同样功能的安全的字符串拷贝函数,减少了缓冲区攻击的可能,strcpy_s。这些函数是以c运行库的方式提供的,当然,不同的操作系统,c运行时库可能不同,但是对c标准库的支持是完全一致的,也就是说,在不同的操作系统上,使用同一个c标准库的函数必然产生一致的结果。
一个C运行库大致包含了如下功能:
* 启动与退出:包括入口函数及入口函数所依赖的其他函数等。
* 标准函数:由C语言标准规定的C语言标准库所拥有的函数实现。(C标准库)
* I/O:I/O功能的封装和实现,参见上一节中I/O初始化部分。
* 堆:堆的封装和实现,参见上一节中堆初始化部分。
* 语言实现:语言中一些特殊功能的实现。
* 调试:实现调试功能的代码。
总结一下,C标准库就是任何平台都可以使用的基本C语言库。而CRT除了将C标准库加入所属范围外,还扩展了与平台相关的接口库,这些接口实现根据不同平台调用不同平台的操作系统API。
如下图所示,采用C标准库编写的程序可以应用到windows平台,也可以应用到linux平台;而用CRT另外与平台相关的库函数编写的应用程序不能跨平台运行。
参考资料:
http://blog.****.net/a379039233/article/details/51062705 FILE以前的数据结构形式
http://blog.****.net/babygjx/article/details/5740038 io.h头文件下的一些函数
http://blog.****.net/lemonrabbit1987/article/details/47970861 C语言标准库概述
https://www.cnblogs.com/renyuan/p/5031100.html 详细分析了C语言标准库和C运行库的区别