标题非常明确:将basename
(man 3 basename
)与__FILE__
一起使用是否安全?
它编译并且似乎工作正常,但 basename
的参数是char*
(不是const char*
)和man
- 页面说:
dirname()和basename()都可以修改path的内容,因此在调用其中一个函数时可能需要传递一个副本。
所以,这让我很担心。
也许问题应该更像:__FILE__
的类型是什么?它不是字符串文字/ const char*
吗?但如果是,为什么没有编译时错误(const char*
到char*
)?
答案 0 :(得分:8)
仔细阅读 basename(3)并注意:
警告:两个不同的功能
basename()
- 见下文。
并照顾 NOTES 说
有两个不同版本的
basename()
- POSIX版本 如上所述,和GNU版本,后面的#define _GNU_SOURCE /* See feature_test_macros(7) */ #include <string.h>
GNU版从不修改其参数,并返回空 path具有尾部斜杠时的字符串
(重点是我的)
因为据说GNU版本没有修改它的参数,所以__FILE__
使用它是安全的
__builtin_basename
,如果给出一个像__FILE__
这样的字符串文字,或者在调用时会在编译时计算基本名称<{1}}在运行时。
请注意basename
有libgen.h
答案 1 :(得分:4)
__FILE__的类型是什么?它不是字符串文字/ const char *?
是。这是一个字符串文字。
但如果是,为什么没有编译时错误(const char * to char *)?
可能是因为你使用的实现(glibc)可能会在你传递的字符串文字中返回一个指针(即它不会修改它的输入)。 在任何情况下,您都不能依赖它,如上所述。
C标准(c11,§6.10.8.1)说__FILE__
是一个字符串文字:
__FILE__
当前源文件的假定名称(字符串siteral)。
POSIX说:
basename()函数可以修改路径指向的字符串, 并且可以返回指向内部存储的指针。返回的指针 可能无效或存储可能被a覆盖 后续调用basename()。
(强调我的)。
所以,不,用basename()
来呼叫__FILE__
是不安全的。您只需复制__FILE__
并在其上执行basename()
:
char *filename = strdup(__FILE__);
if (filename) {
/* error */
}
char *file_basename = basename(filename);
free(filename);
由于__FILE__
是字符串文字,因此使用数组是另一种选择:
char filename[] = __FILE__;
char *file_basename = basename(filename);