【讨论】关于内存查找的最快算法

choco1234 2006-07-24 02:29:23
自己写了个程序仿照 OD 的内存数据查找功能,比如在内存中查找 ff 25 ?? ?? ?? ?? c3。
然后做了个测试:
被查找文件大小:1M
特征字符串长度:6字节 (改特征字符串不存在)
循环:10000次
CPU:P4 3.0G
结果:用了约12s

我觉得自己的算法不好,竟然用了这么多时间。
希望大家可以指点下。

附程序:
// BinFind.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

LPBYTE FindBin(LPBYTE lpBuf, size_t iBufBytes, LPBYTE lpMarkBuf, LPBYTE lpMarkFormat, size_t iMarkBufBytes);

int _tmain(int argc, _TCHAR* argv[])
{
//BYTE data[] = {0x80, 0x39, 0x00, 0x75, '?', '?', 0xff};
//BYTE format[] = {'-', '-', '-', '-', '?', '?', '-'};
BYTE data[] = {0x80, 0x39, 0x00, 0x75, 0x03, 0x0};
BYTE format[] = {'-', '-', '-', '-', '-', '-',};

TCHAR *lpszFileName = _T("abc.exe");
HANDLE hFile = CreateFile( lpszFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );

DWORD dwFileSize = GetFileSize(hFile, NULL);

HANDLE hMapFile = CreateFileMapping( hFile,
NULL,
PAGE_READONLY,
0,
0,
NULL );

LPBYTE lpFile = (LPBYTE)MapViewOfFile( hMapFile,
FILE_MAP_READ,
0,
0,
0 );

DWORD i=10000;
LPBYTE lpAddr;
DWORD dw1 = GetTickCount();
while (--i)
lpAddr = FindBin(lpFile, dwFileSize, data, format, sizeof(data));
DWORD dw2 = GetTickCount();
printf("%x \n", lpAddr);
printf("%d \n", dw2-dw1);

return 0;
}

LPBYTE FindBin(LPBYTE lpBuf, size_t iBufBytes,
LPBYTE lpMarkBuf, LPBYTE lpMarkFormat, size_t iMarkBufBytes)
{
LPBYTE lpdata = lpBuf;
size_t size = iBufBytes;
BYTE CmpData = *lpMarkBuf;
BOOL result = FALSE;

while (size > 0)
{
// 查找第1个字符
while ((--size) && (*lpdata != CmpData))
lpdata++;
if (*lpdata != CmpData)
break; // 没有找到

if (size < iMarkBufBytes)
break; // 剩余比较的字节不够

// 比较特征字符
LPBYTE lp1 = lpdata + 1;
LPBYTE lp2 = lpMarkBuf + 1;
LPBYTE lp3 = lpMarkFormat + 1;
size_t j = iMarkBufBytes - 1;
while (--j)
{
if ((*lp3 != '?') && (*lp1 != *lp2))
break;
lp1++, lp2++, lp3++;
}
if (*lp1 == *lp2)
{ // 找到了
result = TRUE;
break;
}

lpdata++;
}

if (result)
return lpdata;
else
return NULL;
}
...全文
4816 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
azk2000 2006-07-31
  • 打赏
  • 举报
回复
1M的文件也用内存映射啊?
KDE 2006-07-26
  • 打赏
  • 举报
回复
学习
jayfans205 2006-07-26
  • 打赏
  • 举报
回复
学习中~
jpsr 2006-07-26
  • 打赏
  • 举报
回复
KMP是不是那个 字符串回溯算法?以前在数据结构书上看过。不过书上没有详细介绍这个算法,只有几个例子。
lisypro 2006-07-26
  • 打赏
  • 举报
回复
用串搜索怎么样呀
奶糖人五号 2006-07-26
  • 打赏
  • 举报
回复
mark
qjf520 2006-07-26
  • 打赏
  • 举报
回复
收获不少啊
province_ 2006-07-26
  • 打赏
  • 举报
回复
你完全可以构造一下直接使用库里自带的串查找函数。
我好象记得WINDOWS核心编程里有关于对文件内容逆序的例子,也是MAP进来后使用库函数做STRREV的,因为这些常规函数都是按最高效率的算法编写的。
lineuser 2006-07-26
  • 打赏
  • 举报
回复
学习学习
lvbinandylau 2006-07-26
  • 打赏
  • 举报
回复
学习了
zoezinsser 2006-07-26
  • 打赏
  • 举报
回复
记号
fox1999 2006-07-25
  • 打赏
  • 举报
回复
我日,广告不少
sfengnet 2006-07-25
  • 打赏
  • 举报
回复
知道微软的搜索为什么在查找第2次或者是多次的时候那么快吗? 因为用了缓存机制,也就是查找出来的数据会按照一定的规则缓存到内存中, 包括google桌面搜索和baidu桌面搜索都使用到了这种机制

参见 windows NT 技术内幕第二版 8.4章 高速缓存数据结构

也就是在算法达到一定极限的时候应该考虑使用其他的方法进行提速,如缓存,如索引,等等

还有一点,在读写内存时尽量一次性取最大所需,这样减少了内存访问的次数,提升了效率

就吹这么多了,呵呵-_-!

fucintosh 2006-07-25
  • 打赏
  • 举报
回复
http://www.ics.uci.edu/~eppstein/161/kmp/

Source code included.
pigsanddogs 2006-07-25
  • 打赏
  • 举报
回复
ni juede zheyang hui kuai ma ...
loushang de
snoopyzzz 2006-07-25
  • 打赏
  • 举报
回复
我是优化狂人,觉得有两个以上比较运算再做逻辑 与/或 运算时可以改成算数 与/或 运算
例如:
if(a==1 && b==2)
可以改成
if(a==1 & b==2)
choco1234 2006-07-25
  • 打赏
  • 举报
回复
to wxc2006()
比如8位长度的,不管是 char 还是 unsigned char,初值为0的话,会循环256次
我写了,是8位长度的,不是说size_t

to iicup
KMP 啥东东来的?
Richard_Hong 2006-07-25
  • 打赏
  • 举报
回复
mark
Lewolf 2006-07-25
  • 打赏
  • 举报
回复
如果是真的使用这个算法很频繁的话,可以考虑自己写一个汇编的代码,肯定会快很多的,对于不同处理器,可以预先进行优化的,比如使用MMX字领SSE指令等肯定效率会大大提高。
Jedimaster 2006-07-25
  • 打赏
  • 举报
回复
对齐了没?
加载更多回复(18)

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧