使用“#define _GNU_SOURCE” 是什么意思?
使用“#define _GNU_SOURCE” 是什么意思?
今天我必须要使用 basename 函数,使用man手册查询了一下这个函数 man 3 basename 发现一个奇怪的信息
名称
basename,dirname-分析路径名组件
简介
#include <libgen.h>
char *dirname(char *path);
char *basename(char *path);
警告:
有两个不同的函数basename()-请参阅下面的。
函数dirname()和basename()将以空结尾的路径名字符串分解为目录和文件名组件。在通常情况下,dirname()返回最后一个“/”之前(但不包括在内)的字符串,basename()返回最后一个“/”之后的组件。尾随的“/”字符不算作路径名的一部分。
如果路径不包含斜杠,dirname()将返回字符串“.”,而basename()将返回路径的副本。如果path是字符串“/”,则dirname()和basename()都会返回字符串“/”。如果path是空指针或指向空字符串,则dirname()和basename()都返回字符串“.”。
将dirname()返回的字符串、一个“/” 和basename()返回的字符串连接起来,将生成完整的路径名.
dirname()和basename()都可能会修改路径的内容,因此在调用这两个函数时传入参数一定是一个路径的副本。
这些函数可能返回指向静态分配内存的指针,这些指针可能会被后续调用覆盖。或者,它们可以返回指向路径某一部分的指针,以便在不再需要函数返回的指针之前,不应修改或释放由路径引用的字符串。
下面的列表(取自SUS V2)显示了dirname()和basename()为不同路径返回的字符串:
path | dirname | basename |
---|---|---|
/usr/lib | /usr | lib |
/usr/ | / | usr |
usr | . | usr |
/ | / | / |
. | . | . |
… | . | … |
返回值
dirname()和basename()都返回指向以空结尾的字符串的指针。(不要将这些指针传递给free(3)。)
ATTRIBUTES
For an explanation of the terms used in this section, see attributes(7).┌──────────────────────┬───────────────┬─────────┐│Interface │ Attribute │ Value │├──────────────────────┼───────────────┼─────────┤│basename(), dirname() │ Thread safety │ MT-Safe │└──────────────────────┴───────────────┴─────────┘
注意
basename()有两个不同的版本————上面描述是posix版本,gnu版本是下面:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <string.h>
GNU版本从不修改它的参数,当路径的结尾是一个斜杠时返回空字符串,特别是当它是“/”时。没有dirname()的GNU版本。
使用glibc,当包含<libgen.h>时,将获得basename()的POSIX版本,否则将获得GNU版本。
漏洞
在glibc实现中,这些函数的posix版本修改了path参数,并在使用诸如“/usr/”之类的静态字符串调用时修改产生段错误。
在glibc 2.2.1之前,dirname()的glibc版本没有正确地处理带有尾随“/”字符的路径名,如果给定了空参数,则会生成段错误。
例子
#include <libgen.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <string.h>
int main(){char *dirc, *basec, *bname, *dname;char *path = "/etc/passwd";dirc = strdup(path);basec = strdup(path);dname = dirname(dirc);bname = basename(basec);printf("dirname=%s, basename=%s\n", dname, bname);return 0;
}
两个问题:
- 如果是这样,为什么不给人们提供不同的头文件,没有必要定义一些模糊的宏来获取函数的实现或者其他啊?
- 还有一些问题也让我抓狂:编译器怎么知道要连接那个函数到可执行文件? 也是使用 #define 的方式吗?
解答一
定义 _GNU_SOURCE 与许可证无关,与编写(非)可移植代码无关。如果您定义了“_GNU_SOURCE ”,您将得到:
- 访问许多非标准的GNU/Linux扩展函数
- 对POSIX标准中省略的传统功能的访问(通常是有充分理由的,例如被更好的替代方案替换,或者与特定的遗留实现绑定)
- 访问不可移植的低级功能,但有时需要实现系统实用程序,如mount、ifconfig等。
对于许多POSIX指定的函数来说,行为是不正常的,GNU人员不同意标准委员会关于函数应该如何运行,并决定自己做一些事情。
只要你知道这些事情,定义 _GNU_SOURCE 就不是问题了,但是你应该避免定义它,而是在可能的时候定义POSIX_C_source=200809L或Xopen_source=700,以确保你的程序是可移植的。
尤其是,你不应该使用的来自GNU来源的东西是上面的2和4。
解答二
如果是这样,为什么不给人们提供不同的头文件,没有必要定义一些模糊的宏来获取函数的实现或者其他啊?
在不同的Unix版本中,同一个头部的内容通常稍有不同,因此没有单一的正确内容,例如,<string.h>—有许多标准(xkcd)。在一整套宏中选择你最想要的,这样,这个库可以满足不同人的标准。
还有一些问题也让我抓狂:编译器怎么知道要连接那个函数到可执行文件? 也是使用 #define 的方式吗?
一种常见的方法是根据 _GNU_SOURCE 是否被定义来有条件的 给标识符 basename 定义不同的名称:
#ifdef _GNU_SOURCE
# define basename __basename_gnu
#else
# define basename __basename_nongnu
#endif
这样库的实现中只要提供两种实现即可。
解答三
来自google的邮件列表
看看 glibc’s include/features.h:
定义了_GNU_SOURCE 表示可以使用
STRICT_ANSI,
_ISOC99_SOURCE,
_POSIX_SOURCE,
_POSIX_C_SOURCE,
_XOPEN_SOURCE,
_XOPEN_SOURCE_EXTENDED,
_LARGEFILE_SOURCE,
_LARGEFILE64_SOURCE,
_FILE_OFFSET_BITS=N,
_BSD_SOURCE,
_SVID_SOURCE 包括 GUN 扩展内容。
因此,它为gcc启用了大量编译标志
解答四
想详细了解 _GNU_SOURCE ,可以看一下下面的文档。
来自 GUN 文档
宏:_GNU_SOURCE
如果您定义这个宏,所有内容都包括在内: ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X/Open, LFS和GUN扩展。在POSIX.1与BSD冲突的情况下,POSIX.1 定义优先。
Linux 的man手册中的功能测试宏:
_GNU_SOURCE
定义这个宏(有任何值)隐式地定义了 _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE,其值为200809L(glibc版本2.10之前的200112L;glibc版本2.5之前的199506L;glibc版本2.1之前的199309L)和_XOPEN_SOURCE ,其值为700(600在2.10之前的glibc版本中;在2.2之前的glibc版本中为500)。此外,还公开了各种特定于GNU的扩展。
自从glibc 2.19以来,定义_GNU_SOURCE也具有隐式定义_DEFAULT_SOURCE的效果。在2.20之前的glibc版本中,定义_GNU_SOURCE还具有隐式定义_BSD_SOURCE 和_SVID_SOURCE的效果。
注意:在包含头文件之前,需要定义_GNU_SOURCE,以便各个头文件启用这些功能。例如:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
...
_还可以使用 -D 标志在每次编译时启用 _GNU_SOURCE:
$ gcc -D_GNU_SOURCE file.c
(-D 不是特定于_GNU_SOURCE,而是以这种方式定义的任何宏)。
使用“#define _GNU_SOURCE” 是什么意思?相关推荐
- linux c 宏定义 #define _GNU_SOURCE 含义
今天我必须要使用 basename 函数,使用man手册查询了一下这个函数 man 3 basename 发现一个奇怪的信息 名称 basename,dirname-分析路径名组件 简介 #inclu ...
- 【编程基础の基础】“#define _GNU_SOURCE“或是在编译时“-D _GNU_SOURCE“代表了什么?有什么用
概念 详细的信息可查看Linux手册 man feature_test_macros 从GNU的文档中: Macro: _GNU_SOURCE If you define this macro, ev ...
- fukk _GNU_SOURCE __USE_GNU
#define _GNU_SOURCE #include "/usr/include/features.h" #ifndef __USE_GNU // 防御检查头文件是否已经启用G ...
- strstr函数头文件_C语言(函数)学习之strstr strcasestr
一.strstr函数使用 [1] 函数原型 char *strstr(const char *haystack, const char *needle); [2] 头文件 #include [3] 函 ...
- linux内核添加c代码,如何从C代码加载Linux内核模块?
Ciro Santill.. 19 最小的可运行示例 使用这个简单的参数打印机模块在QEMU + Buildroot VM和Ubuntu 16.04主机上进行了测试. 我们使用init_module/ ...
- 在Ubuntu 16.04.1 LTS上测试Linux AIO功能实录
我们知道nginx中有libaio这项功能,为了研究AIO的一些常用接口用法,在网上找到一个例子,异步IO读取本地文件,亲自实践了一把,记录如下: 安装依赖库 在Ubuntu 16.04上需要事先安装 ...
- linux进程间通信:shell管道 | 的实现
文章目录 介绍 重定向函数介绍 总结 linux terminal输入如下命令,其中"|"符号即为我们上文中所说的无名管道 介绍 正如我们上文中所描述的"|"无 ...
- ACCEPT()和ACCEPT4()
ACCEPT 章节:Linux 程序员手册 (2) 更新:2010-09-10 到 易美翻译 翻译 名字 accept - 通过套接口接受一个连接 概要 #include Esys/types.h&g ...
- Nginx源码分析--数据对齐posix_memalign和memalign函数
posix_memalign函数() /* * 背景: * 1)POSIX 1003.1d * 2)POSIX 标明了通过malloc( ), calloc( ), 和 re ...
- posix_memalign
翻译的<Linux system programming> 第八章 二 ;<Linux System Programming>中文版 对齐 数据的对齐(alignment)是指 ...
最新文章
- 高并发服务优化篇:从RPC预热转发看服务端性能调优
- 软件工程作业2.1:阐述对软件工程的理解,学完这门课自己能学到什么,学完后能做什么...
- 一个数据仓库时代开始--Hive
- android插件式换肤,Android学习之插件化换肤
- windows2008下配置iis时出现错误“由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。”...
- 使用Filter防止浏览器缓存页面或请求结果
- 显卡天梯图2022年4月 最新显卡性能排行天梯图
- 应用计算机测线性电阻伏安特性曲线,伏安特性曲线
- ESXI7.0下载地址
- Scratch的安装与界面介绍
- OJ每日一练——过滤多余的空格
- Three.js三角形Triangle
- python爬虫爬取steam,epic,origin平台游戏数据
- js 数组遍历时删除元素方法总结
- 李斌转让5000万股私人持有股份 完成蔚来用户信托设立
- 【织恋袜业】一双袜子的数字化之路——写在第十四届中国·大唐国际袜业博览会开幕前(下)
- 首批小程序出炉,小游戏?
- JAVA里面继承和接口
- windows64位系统完全卸载winpcap的方式
- 如何掌握二维码的扫描数据?
热门文章
- 深度点击率预估模型的One-Epoch过拟合现象剖析
- Black-Scholes期权定价模型
- mmdetection中使用训练好的模型单张图片推理并保存到文件夹
- 内边距怎么设置html,如何设置内边距
- echart 三维可视化地图_Echarts三维坐标系
- 管理学概念区分(行为科学、科学管理、古典管理理论)
- html主菜单和子菜单,刻录dvd光盘设置dvd菜单 只要子菜单可以吗 不要主菜单的
- GRUB和LILO的区别
- html 页面没有鼠标,网页上鼠标箭头不见了 电脑上不显示鼠标箭头怎么办?
- Vue中@click.stop与@click.prevent、@click.native