是否有可能在 C++ 中获取进程内存中第一个字符串的地址?

Is it possible to get the address of the first string in memory of a process in c++?

C++能否获取进程内存中第一个字符串的地址? 就像我不必遍历整个进程的内存来查找字符串一样,但我可以从第一个字符串的地址开始迭代?我说的是寻找任何类型变量的第一个,而不仅仅是字符串,尽管我用它作为例子。 让我在代码中举个例子:

for (int i = 1; i < 10000000; i++)
{
    std::string buf;
    ReadProcessMemory(hproc, (LPCVOID)i, &buf, sizeof(std::string), NULL);
    std::cout << buf << std::endl;
}

这有必要吗?我不能只从第一个字符串的地址开始,或者用其他方式更快吗?

Std 字符串使用与使用 operator new 分配的所有其他对象相同的堆来分配其内部存储。没办法区分各种内容。

也就是说,从纯粹的智力练习中,可以使用自定义分配器声明您自己的 basic_string 实现,您可以在其中观察内存分配和释放。

std::basic 字符串的完整模板定义是:

template<
    class CharT,
    class Traits = std::char_traits<CharT>,
    class Allocator = std::allocator<CharT>
> class basic_string;

而 std::string 实际上是 std::basic_string<char>,依赖于 Traits 和 Allocator 的默认值。

您可以在其中提供您自己的分配器实现,例如,它可以记录您的程序执行的分配和释放,或者将分配按顺序存储在一些连续的存储中。您只会跟踪您明确声明的字符串。

请注意,在使用不同分配器的标准容器之间禁用移动语义,并且在许多情况下,调用以 return 字符串作为参数的 std 库方法将调用自定义字符串和标准分配的字符串之间的副本版本,因此该视图可能仍然不是真实视图。

据我了解,std::string的当前实现只是将字符内容存储在分配的存储中,但可以将其他信息存储在分配的space中以帮助管理字符串增长。

请注意,字符串的容量和当前长度存储在也指向此缓冲区的 std::string 对象中,因此很难推断出有关已分配缓冲区内容的有用信息。如果它被用作合法的字符串,那么 c++ 标准说它是零终止的;所以这表明它可以被视为 C char* 字符串。

许多实现通过将它们内联存储在没有动态分配的 std::string 对象中来优化非常小的字符串。他们依靠一些任意规则来理解当前的布局(nullptr 或动态或内联),例如“知道”容量,一个 64 位整数,永远不会大于 56 位值,所以“最高字节”总是动态字符串为零;但实际上是内联字符串的 1byte size(),具有恒定的最大大小:然后剩余的字节可用于内联内容,可能最多 23 个字符!

但其他方案也是可能的。例如,旧的 Microsoft 字符串(不是 std::string)用于在开始时将所有长度和容量信息存储在指向对象中,而字符串对象是指向缓冲区下一个文本部分的简单指针。这在 printf() 中使用非常方便!其他 pre-c++11 std::string 系统试图共享字符串和存储的引用计数,但 c++11 的“生命周期”规则几乎无法维持。