2011-01-14 7 views
0

연습으로 C++로 쓰는 메모리 스캐너에서 일치하지 않는 결과를 제거하려고합니다. 메모리를 처음 스캔하면 모든 결과가 _results 벡터에 저장됩니다.액세스 위반 C ​​++ (벡터에서 항목 삭제)

나중에 _results을 다시 스캔하여 더 이상 일치하지 않는 항목을 지워야합니다.

오류 다음 std::vector<T> 대상 항목을 삭제 한 후 기본 배열의 연속을 유지하기 위해 주변 요소를 이동합니다 이후 std::vector<T>에서

Unhandled exception at 0x004016f4 in .exe: 0xC0000005: Access violation reading location 0x0090c000.

// Receives data 

DWORD buffer; 

for (vector<memblock>::iterator it = MemoryScanner::_results.begin(); it != MemoryScanner::_results.end(); ++it) { 
    // Reads data from an area of memory into buffer 
    ReadProcessMemory(MemoryScanner::_hProc, (LPVOID)(*it).address, &buffer, sizeof(buffer), NULL); 

    if (value != buffer) { 
     MemoryScanner::_results.erase(it); // where the program breaks 
    } 
} 
+0

에서 제공하는 코드는 질문에 대답하기에 충분 완료 될 것 같지 않습니다. –

+0

필자는이 형식이 지우기 선을 명시 적으로 가리키는 액세스 위반이기 때문에 유형이 관련성이 없다고 생각했습니다. –

답변

5

삭제 요소가 it 반복자를 무효화됩니다. 잘못된 반복자를 역 참조하려고 결국하지 않도록

다행히 vector<T>::erase()는 유효한 새 반복자를 반환

DWORD buffer; 
vector<memblock>::iterator it = MemoryScanner::_results.begin(); 
while(it != MemoryScanner::_results.end()) 
{ 
    ReadProcessMemory(MemoryScanner::_hProc, (LPVOID)(*it).address, 
     &buffer, sizeof(buffer), NULL); 
    if (value != buffer) 
    { 
     it = MemoryScanner::_results.erase(it); 
    } 
    else 
    { 
     ++it; 
    } 
} 

벡터에서 항목을 삭제하는 또 다른 방법을

erase-remove idiom을 사용해 보셨습니까?

struct RemoveNonMatches 
{ 
public: 
    RemoveNonMatches(HANDLE p, DWORD v) : proc(p) val(v) {} 

    bool operator()(const memblock& obj) 
    { 
     DWORD buffer; 
     ReadProcessMemory(proc, static_cast<LPVOID>(obj.address), 
      &buffer, sizeof(buffer), NULL); 
     return (buffer != val); 
    } 

private: 
    HANDLE proc 
    DWORD val; 
}; 

// ... 

MemoryScanner::_results.erase 
(
    std::remove_if 
    (
     MemoryScanner::_results.begin(), 
     MemoryScanner::_results.end(), 
     RemoveNonMatches(MemoryScanner::_hProc, value) 
    ), 
    MemoryScanner::_results.end() 
); 
+0

'it = MemoryScanner :: _ results.erase (it);'고치지 않았습니다. –

+0

아, 방금 else 문을 잊어 버렸습니다. 고마워. –

1

vector::eraseerase()에 전달 된 반복자를 무효화합니다. 그런 다음 증분을 시도합니다. UB가 계속된다. 완전성에 대한

0

std::remove_if 버전 :

bool has_bad_memory_contents(const memblock& block) { 
    DWORD buffer; 
    ReadProcessMemory(
     MemoryScanner::_hProc, (LPVOID)block.address, 
     &buffer, sizeof(buffer), NULL 
    ); 
    return buffer != value; 
} 

std::vector<memblock>& r = MemoryScanner::_results; 
r.erase(std::remove_if(r.begin(), r.end(), has_bad_memory_contents), r.end());