跳转至

字符串数据

大多数开发者使用「字符串」一词时好像它与文本同义,但文本只是字符串最常见的用途。在低层,字符串只是任意数值对象的数组,在内存中看起来线性且不对齐。清单 4-2 显示了四个文本字符串声明。

// char 每个字符 1 字节
char* thinStringP = "my_thin_terminated_value_point
er";
char thinStringA[40] = "my_thin_terminated_value_ar
ray";
// wchar_t 每个字符 2 字节
wchar_t* wideStringP = L"my_wide_terminated_value_p
ointer";
wchar_t wideStringA[40] = L"my_wide_terminated_valu
e_array";

清单 4-2:在 C++ 中声明几个字符串

在文本语境中,字符串保存字符对象(8 位编码用 char,16 位编码用 wchar_t),每个字符串的结尾由 null 终止符(等于 0x0 的字符)指定。让我们看看这些变量存储的内存,如图 4-3 中的两个内存转储所示。

是清单 4-2 中存储的文本。

如果你不习惯阅读内存,OllyDbg 转储此时可能有点难懂。

图 4-3 字符串数据的 OllyDbg 内存转储:ASCII 列中的人类可读文本就

联。窗格地址大小数据对象窗格 1

窗格 1

窗格 1

窗格 1

窗格 1

窗格 1 窗格 2

窗格 2

窗格 2

窗格 2

窗格 2

窗格 2

在图 4-3 中,窗格 1 显示 thinStringP(地址 0x01243040)和 wideStringP(地址 0x0124306C)在内存中占用的值只有 4 字节长,不包含字符串数据。这是因为这些变量实际上是指向各自数组第一个字符的指针。例如,thinStringP 包含 0x012420F8,在图 4-3 的窗格 2 中,你可以在地址 0x012420F8 看到 my_thin_terminated_value_pointer。

看看窗格 1 中这些指针之间的数据,你可以看到 thinStringA 和 wideStringA 存储的文本。此外,注意 thinStringA 和 wideStringA 在 null 终止符之外还有填充;这是因为这些变量被声明为长度 40 的数组,所以它们被填满到 40 个字符。