使用带有__FILE__的`basename`是否安全?

Kir*_*rov 1 c c++ posix

标题非常清楚:使用basename(man 3 basename)是否安全__FILE__


它编译并且似乎工作正常,但是 basename参数是char*(不是const char*),- manpage表示:

dirname()和basename()都可以修改path的内容,因此在调用其中一个函数时可能需要传递一个副本.

所以,这让我担心.

也许问题应该更像:什么类型的__FILE__?这不是字符串文字/ const char*?但如果是,为什么没有编译时错误(const char*to char*)?

Bas*_*tch 8

仔细 阅读basename(3)并注意:

警告:有两种不同的功能basename()- 见下文.

并照顾NOTES

有两个不同的版本basename()- 上面描述的POSIX版本,以及GNU版本,后者可以使用

      #define _GNU_SOURCE         /* See feature_test_macros(7) */
      #include <string.h>
Run Code Online (Sandbox Code Playgroud)

GNU版本从不修改其参数,并在路径具有尾部斜杠时返回空字符串

(重点是我的)

因为据说GNU版本没有修改它的参数,所以使用它是安全的 __FILE__

顺便说一句,您可以考虑自定义GCC(例如使用MELT)来定义一些__builtin_basename在编译时计算基本名称的内容,如果给定字符串文字__FILE__basename在运行时调用.

请注意,libgen.h#define basename __xpg_basename

  • 如果包含`<libgen.h>`AFAICS,则只能获得POSIX版本; 有关详细信息,请参阅[POSIX规范](http://pubs.opengroup.org/onlinepubs/9699919799/functions/basename.html).如果使用glibc,GNU版本是默认版本. (2认同)

P.P*_*.P. 5

\n

__FILE__ 的类型是什么?它不是一个字符串文字/const char* 吗?

\n
\n\n

是的。这是一个字符串文字。

\n\n
\n

但如果是的话,为什么没有编译时错误(const char* 到 char*)?

\n
\n\n

可能是因为您使用的实现(glibc's)可能会在您传递的字符串文字中返回一个指针(即它不会修改其输入)。\n无论如何,您都不能依赖它来实现上面叙述如下。

\n\n

C 标准 (c11, \xc2\xa7 6.10.8.1) 表示这__FILE__是一个字符串文字:

\n\n
\n

__FILE__当前源的假定名称 \xef\xac\x81le (字符串站点)。

\n
\n\n

POSIX说:

\n\n
\n

basename() 函数可以修改 path 指向的字符串,并且可以返回指向内部存储的指针。返回的指针可能会失效,或者存储可能会被后续调用 basename() 覆盖。

\n
\n\n

(强调我的)。

\n\n

basename()所以,不,使用拨打电话并不安全__FILE__。您只需复制一份__FILE__basename()对其进行操作即可:

\n\n
char *filename = strdup(__FILE__);\nif (filename) {\n    /* error */\n}\nchar *file_basename = basename(filename);\nfree(filename);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

由于__FILE__是字符串文字,使用数组是另一种选择:

\n\n
char filename[] = __FILE__;\nchar *file_basename = basename(filename);\n
Run Code Online (Sandbox Code Playgroud)\n

  • 为什么是“strdup”?只需分配一个本地缓冲区...`char filename[]=__FILE__`。 (4认同)