将 `basename` 与 __FILE__ 一起使用安全吗?
Is it safe to use `basename` with __FILE__?
标题很清楚:Is it safe to use basename
(man 3 basename
) with __FILE__
?.
它编译并且似乎工作正常,但是 basename
的参数是char*
(不是const char*
) 和 man
-页面说:
Both dirname() and basename() may modify the contents of path, so it may be desirable to pass a copy when calling one of these functions.
所以,这让我很担心。
也许问题应该更像是:__FILE__
的类型是什么?不就是字符串字面量/const char*
吗?但如果是,为什么没有 compile-time 错误(const char*
到 char*
)?
仔细阅读basename(3)并注意:
Warning: there are two different functions basename()
- see below.
并注意 NOTES 说法
There are two different versions of basename()
- the POSIX version
described above, and the GNU version, which one gets after
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <string.h>
The GNU version never modifies its argument, and returns the empty
string when path has a trailing slash
(重点是我的)
因为据说GNU版本没有修改它的参数,使用它是安全的 __FILE__
顺便说一句,您可以考虑自定义您的 GCC(例如使用 MELT)来定义一些 __builtin_basename
,如果给定一个像 __FILE__
或这样的字符串文字,它将在编译时计算基名否则在运行时调用 basename
。
注意 libgen.h
有 #define basename __xpg_basename
what is the type of __FILE__? Isn't it a string literal / const char*?
是的。这是一个字符串文字。
But if it is, why there's no a compile-time error (const char* to char*)?
可能是因为您使用的实现(glibc 的)可能会在您传递的字符串文字中返回一个指针(即它不会修改其输入)。
无论如何,您不能依赖它来完成以下所述。
C 标准 (c11, § 6.10.8.1) 说 __FILE__
是一个字符串文字:
__FILE__
The presumed name of the current source file (a character string siteral).
POSIX 说:
The basename() function may modify the string pointed to by path,
and may return a pointer to internal storage. The returned pointer
might be invalidated or the storage might be overwritten by a
subsequent call to basename().
(强调我的)。
所以,不,用 __FILE__
调用 basename()
是不安全的。您可以简单地复制 __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);
标题很清楚:Is it safe to use basename
(man 3 basename
) with __FILE__
?.
它编译并且似乎工作正常,但是 basename
的参数是char*
(不是const char*
) 和 man
-页面说:
Both dirname() and basename() may modify the contents of path, so it may be desirable to pass a copy when calling one of these functions.
所以,这让我很担心。
也许问题应该更像是:__FILE__
的类型是什么?不就是字符串字面量/const char*
吗?但如果是,为什么没有 compile-time 错误(const char*
到 char*
)?
仔细阅读basename(3)并注意:
Warning: there are two different functions
basename()
- see below.
并注意 NOTES 说法
There are two different versions of
basename()
- the POSIX version described above, and the GNU version, which one gets after#define _GNU_SOURCE /* See feature_test_macros(7) */ #include <string.h>
The GNU version never modifies its argument, and returns the empty string when path has a trailing slash
(重点是我的)
因为据说GNU版本没有修改它的参数,使用它是安全的 __FILE__
顺便说一句,您可以考虑自定义您的 GCC(例如使用 MELT)来定义一些 __builtin_basename
,如果给定一个像 __FILE__
或这样的字符串文字,它将在编译时计算基名否则在运行时调用 basename
。
注意 libgen.h
有 #define basename __xpg_basename
what is the type of __FILE__? Isn't it a string literal / const char*?
是的。这是一个字符串文字。
But if it is, why there's no a compile-time error (const char* to char*)?
可能是因为您使用的实现(glibc 的)可能会在您传递的字符串文字中返回一个指针(即它不会修改其输入)。 无论如何,您不能依赖它来完成以下所述。
C 标准 (c11, § 6.10.8.1) 说 __FILE__
是一个字符串文字:
__FILE__
The presumed name of the current source file (a character string siteral).
POSIX 说:
The basename() function may modify the string pointed to by path, and may return a pointer to internal storage. The returned pointer might be invalidated or the storage might be overwritten by a subsequent call to basename().
(强调我的)。
所以,不,用 __FILE__
调用 basename()
是不安全的。您可以简单地复制 __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);