在内存中搜索字符串会导致崩溃 我对C++不太好,但是我在内存中遇到了一个字符串扫描问题。
下面是我的代码的一个小示例:在内存中搜索字符串会导致崩溃 我对C++不太好,但是我在内存中遇到了一个字符串扫描问题。,c++,memory,C++,Memory,下面是我的代码的一个小示例: for (unsigned int i = 0x400000; i < 0xFFFFFFFFFF; i++) { string s = (char *) i; if (s[0] == 'H') { if (s == "Hello") { cout << "Found at address: " << i << endl; } } } for(无
for (unsigned int i = 0x400000; i < 0xFFFFFFFFFF; i++) {
string s = (char *) i;
if (s[0] == 'H') {
if (s == "Hello") {
cout << "Found at address: " << i << endl;
}
}
}
for(无符号整数i=0x400000;i<0xffffffff;i++){
字符串s=(char*)i;
如果(s[0]=='H'){
如果(s==“你好”){
延迟任意指针值(地址)是一种未定义的行为,因平台和操作系统而异
崩溃是许多未定义的行为之一。尽管标签中没有提到它,但基于对ReadProcessMemory
的提及,我假设您希望在Windows中使用它
要在Windows中实现这一点,您几乎需要使用VirtualQuery
来确定地址空间的哪些部分是可用的(在64位系统上尤其重要,在64位系统中,有效地址比32位系统上少得多)
使用VirtualQuery查找可搜索块的代码可能如下所示:
#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <algorithm>
#include <iterator>
template <class InIter1, class InIter2, class OutIter>
void find_all(InIter1 buf_begin, InIter1 buf_end, InIter2 pat_begin, InIter2 pat_end, OutIter output) {
for (auto pos = buf_begin;
buf_end != (pos = std::search(pos, buf_end, pat_begin, pat_end));
++pos)
{
*output++ = (void *)pos;
}
}
template <class outIter>
void find_locs(std::string const &pat, outIter output) {
unsigned char *p;
MEMORY_BASIC_INFORMATION info;
for ( p = nullptr;
VirtualQuery(p, &info, sizeof(info)) == sizeof(info);
p += info.RegionSize )
{
if (info.State == MEM_COMMIT &&
(info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
{
find_all(p, p + info.RegionSize, pat.begin(), pat.end(), output);
}
}
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <pattern>", argv[0]);
return 1;
}
find_locs(argv[1], std::ostream_iterator<void *>(std::cout, "\n"));
}
#包括
#包括
#包括
#包括
#包括
#包括
模板
void find_all(InIter1 buf_begin、InIter1 buf_end、InIter2 pat_begin、InIter2 pat_end、OutIter输出){
对于(自动位置=buf_开始;
buf_end!=(pos=std::search(pos,buf_end,pat_begin,pat_end));
++pos)
{
*输出++=(void*)位置;
}
}
模板
无效查找位置(标准::字符串常量和pat,输出){
无符号字符*p;
内存\基本信息\信息;
对于(p=nullptr;
虚拟查询(p,&info,sizeof(info))==sizeof(info);
p+=信息区域大小)
{
如果(info.State==MEM_COMMIT&&
(info.Type==MEM_-MAPPED | | info.Type==MEM_-PRIVATE))
{
查找所有(p,p+info.RegionSize,pat.begin(),pat.end(),output);
}
}
}
int main(int argc,字符**argv){
如果(argc!=2){
fprintf(stderr,“用法:%s”,argv[0]);
返回1;
}
查找位置(argv[1],std::ostream\u迭代器(std::cout,“\n”);
}
预计会出现一些“虚假”匹配。特别是,即使您搜索的字符串没有出现在进程内存空间的其他任何位置,也会有一个副本作为argv
的一部分,并且(至少)对于传递给find_locs
的临时std::string
,还有一个匹配项,因此对于可能传递的任何字符串,至少要有两个匹配项
您可能还需要通读文档中的内存\u基本信息。我已经选择了(我非常确定)可以安全读取的块子集(即提交的、映射的或私有的)但是,根据您要查找的内容,您可能希望将其更改为仅通过程序文本而不是文本和数据进行搜索。Thisstring s=(char*)i;
将导致未定义的行为。i
不是以null结尾的字符串。是的,我意识到了这一点,但问题是如何修复它?或者用任何其他方法防止它崩溃?VirtualQuery
可以告诉您哪些地址空间区域由实际内存支持。或者,您可以使用IsBadRe进行探测adPtr
。或者,您可以继续并访问\uuuuu try/\uuuuu except
块下的内存,并适当地处理SEH异常。字符串
是不必要的,可能会尝试分配任意数量的内存-char*s=(char*)i;如果(*s='H')…
。否,则(char i)i
自身强制转换不会导致崩溃。尝试从结果指针构造std::string
会导致崩溃(因为构造函数尝试读取指向的内存)。删除std::string
,使用普通char*
指针和C样式比较(请参见例如memcmp
)我已经说过,在最初的问题中,我只是想知道是否有可能防止崩溃,或者至少有另一种方法。这取决于平台和操作系统,没有通用的方法。需要传递的参数是什么?我看到有一种“模式”有吗?@John:就目前的情况而言,您可以像这样运行它:搜索“我的字符串”
。尽管有“模式”,它实际上只搜索文字匹配。