【发布时间】:2019-06-06 06:06:29
【问题描述】:
我有非常大的代码库,它广泛使用__FILE__ 进行日志记录。但是,它包含完整路径,这 (1) 不需要,(2) 可能会导致安全违规。
我正在尝试编写编译时子字符串表达式。结束于this solution
static constexpr cstr PastLastSlash(cstr str, cstr last_slash)
{
return *str == '\0' ? last_slash : *str == '/' ? PastLastSlash(str + 1, str + 1) : PastLastSlash(str + 1, last_slash);
}
static constexpr cstr PastLastSlash(cstr str)
{
return PastLastSlash(str, str);
}
// usage
PastLastSlash(__FILE__);
这很好用,我检查了汇编代码,行在编译时被修剪,只有文件名存在于二进制文件中。
但是,这种表示法过于冗长。我想为此使用宏,但失败了。上面链接中的建议示例
#define __SHORT_FILE__ ({constexpr cstr sf__ {past_last_slash(__FILE__)}; sf__;})
不适用于 MSVC 编译器(我使用的是 MSVC 2017)。使用c ++ 17还有其他方法吗?
UPD1:由函数https://godbolt.org/z/tAU4j7修剪的clang
UPD2: 看起来可以使用函数对编译时间进行修整,但完整的字符串会以二进制形式存在。
【问题讨论】:
-
我无法重现“这很好用,我检查了汇编代码,行在编译时被修剪,只有文件名存在于二进制文件中。”使用最新的 GCC 和 clang:godbolt.org/z/tFR_2D 此外,在 MSCV 中使用
/Ox,即使对于原始past_last_slash(__FILE__),也可以看到完整路径:godbolt.org/z/B1M1nR -
另外,这个宏似乎不是有效的 C++ 代码,但 gcc 扩展:gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html 和
--pedanticgcc 拒绝它。 -
嗯,奇怪,godbolt 未能在 MSVC 的编译时做到这一点......我将尝试提供一些工作示例。
-
您的 Godbolt 演示显示完整的字符串 (
"./example.cpp") 仍存储在可执行文件中。编译器只是在编译时计算一个偏移量 (mov edi, offset .L.str+2)。 -
在很久以前,当我关心这个时,我传递了一个备用文件名
'-D__ALTNAME__="1234.cpp"',然后在#includes 之后立即放置#line __LINE__ __ALTNAME__。请注意,这会使编译器在 1234.cpp 中报告错误。