首页
社区
课程
招聘
[讨论]关于内存查找的最快算法
发表于: 2006-7-24 14:08 5019

[讨论]关于内存查找的最快算法

2006-7-24 14:08
5019
自己写了个程序仿照 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;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 462
活跃值: (18)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
我乱谈几句吧:
1.把你的abc.exe 上传一下,大家好一起测试啊


2.我没仔细看你的算法,但是我在你原来的程序你基础上增加6行,查找速度会提高一倍甚至几倍

3.我增加后的代码:
#include "stdafx.h"
#include <windows.h>

#define MAX_BUF 1024*1024         

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

LPBYTE *buf=new LPBYTE[MAX_BUF+1];//定义了一个大空间

int _tmain(int argc, _TCHAR* argv[])
{
  //BYTE data[]   = {0x80, 0x39, 0x00, 0x75, '?', '?', 0xff};
  //BYTE format[] = {'-',  '-',  '-',  '-',  '?', '?', '-'};
        memset(buf,0x00,MAX_BUF+1);   //将其初始化为0
  unsigned char data[]   = {0x80, 0x39, 0x00, 0x75, 0x03, 0x0};
  unsigned char 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);

  UnmapViewOfFile(lpFile);    //楼主忘了取消映射了
  CloseHandle(hFile);        //还有关闭文件句柄
delete [] buf;         //将临时内存释放
  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;

  if(memcmp(lpMarkBuf,buf,iMarkBufBytes)==0)   //比较看要查找的内容是否是上次查找过了,如果是,则直接返回上次查找的结果
        {
                        return *buf;
        }

  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)
  {
    memcpy(buf,lpdata,iMarkBufBytes);  //找到了之后将找到的内容暂时存储到内存空间
    return lpdata;
  }
  else
    return NULL;

       

}
2006-7-24 20:50
0
雪    币: 231
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
恩,我没法传附件。另外,随便找个文件,自己定义个特征字符也可以的。
句柄什么的确忘记关了 = = 习惯不好。

按你那么改的话,只是加了个BUF而已,而且当我要查找下1个位置的时候,将无法正常工作啊。
2006-7-25 08:35
0
雪    币: 462
活跃值: (18)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
下一个位置的时候你就应该建立一个类似于结构体的东东了

typedef hash_map<size_t,LPBYTE>FIND_RESULT;

第一个里存放当前查找的位置,第二个里存放查找到的数据
2006-7-25 10:04
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
5
KMP算法可以达到 O(M+N)。但是似乎……呵呵,我就不说了
2006-7-25 10:28
0
游客
登录 | 注册 方可回帖
返回
//