首页 > 解决方案 > 返回从 volatile 标量初始化的字符串表现得很奇怪?

问题描述

我试图用字符串文字使逆向工程变得更加困难,比如第一个代码块。我将它初始化为带有挥发物的标量。它是易失的,因此编译器不会对其进行优化并在编译时将其转换为纯字符串文字。

#include <stdio.h>
static const volatile char a = 'a', b = 'b', c = 'c', d = 'd', e = 'e', f = 'f';
inline const char *_GetString(void) {
    return (const char[]){a, b, c, d, e, f, 0};
}
const char *GetString(void) {
    const char *x = _GetString();
    puts(x);
    return x;
}

int main(int argc, char *argv[]) {
    puts(GetString());
    return 0;
}

前面不会打印abcdef两次。但是,这样做:

#include <stdio.h>
const char *_GetString(void) {
    return "abcdef";
}
const char *GetString(void) {
    const char *x = _GetString();
    puts(x);
    return x;
}

int main(int argc, char *argv[]) {
    puts(GetString());
    return 0;
}

为什么会这样?我怎样才能以这种方式从函数中返回一个字符串,这并不奇怪,但仍然保持函数是内联的并且难以进行逆向工程?

标签: carraysstring

解决方案


复合文字,就像第一个_GetString代码片段中的内部文字一样,与在同一范围内声明的任何变量具有相同的生命周期。所以当函数返回时,它返回一个指向数组中第一个元素的指针,即一个指向局部变量的指针。这意味着当函数返回时,返回的指针值不再有效,并且尝试使用它会调用未定义的行为

第二段代码之所以有效,是因为它返回字符串文字的第一个元素的地址,而字符串文字的生命周期是整个程序的生命周期,因此指针仍然有效。


推荐阅读