将 `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);