判断const char*是字符串字面值还是变量

Decide if const char* is a string literal or a variable

本文关键字:字面值 变量 字符串 判断 char const      更新时间:2023-10-16

是否有任何简单的方法来检测,如果参数传递给一个函数(const char *argument)是常量还是变量?

我试图修复一些代码中的错误,这些代码中充满了IsBadWritePtr调用,如果参数是常量,则会抛出访问违反异常。

这是一个可怕的设计愚蠢,但现在我不允许改变尴尬的行为。

您可以添加不同的重载,这将更好地匹配字符串文字。这不是真正的科学,而只是启发式:

void f(const char* p); // potential literal
void f(char *p);       // pointer to non-const

另一个想法是利用字面量实际上是数组:

template <int N>
void f(const char (&_)[N]); // potential literal 

请注意,它们并不完全检测文字不是文字,而是一些其他特性。const char* p = createANewString(); f(p);将解析为f(const char*), const char x[] = { 'A', 'b', 'c', '' };将解析为模板。它们都不是字面量,但您可能不想修改它们。

一旦你做了这样的改变,就应该很容易找到每个重载被调用的位置。

这一切都是在主函数不应该把参数作为const char*的前提下工作的,如果它在内部修改它,你所面临的问题是,因为向后兼容性,你的编译器允许调用一个函数,它需要一个指向非const的指针与文字…

我不认为有一种方法可以检测到这一点,至少不使用一些黑客。
由于接口采用const char *,该函数的责任是无论如何都不修改传递的字符串。您需要修改实现,因为它根本不正确。

VirtualQuery可以用来检测地址是可写的、只读的还是不可访问的。检查返回的MEMORY_BASIC_INFORMATION结构体的StateProtect成员,看看内存是否可访问并且具有所需的访问权限。

一种非常简单的方法是检查指针是否在。rdata段中。

在构建后使用dumpbin /headers来检索.rdata部分的偏移量和长度,或者自己解析PE头。当然,这是特定于工具链的,通常是一个坏主意。此外,如果代码需要与dll互操作,则必须检查几个可执行文件和几个.rdata段。