2012-11-14 4 views
0

키 및 값으로 메모리 주소 또는 포인터 형식을 사용하려고하지만 어떤 이유로 삽입시 액세스 위반이 발생합니다.포인터/주소를 키 및 값으로 사용하면 액세스 위반이 CMap 또는 std :: map

class SomeClass 
{ 
public: 
    std::map<MyClass*, MyClass*> stlMapPointer; 
    std::map<size_t, size_t> stlMapAddress; 
    CMap<MyClass*, MyClass*, MyClass*, MyClass*> mfcMapPointer; 
    CMap<size_t, size_t, size_t, size_t> mfcMapAddress; 
} 

SomeOtherClass 
{ 
public: 
    SomeClass *m_someClassRef; 
    void SomeOtherClass::some_method(MyClass* ptr, ...); 
} 

void SomeOtherClass::some_method(MyClass* ptr, ...) 
{ 
    MyClass* test = ptr; 
    size_t address = reinterpret_cast<size_t>(test); // I realize size_t is technically not portable 

    // PROBLEM STARTS HERE: Every single one of the following insertions will yield an access violation while calling various internal CMap/std::map calls. 
    m_someClassRef->stlMapPointer.insert(std::pair<MyClass*, MyClass*>(test, test)); 
    m_someClassRef->stlMapPointer.insert(std::pair<size_t, size_t>(address, address)); 
    m_someClassRef->mfcMapPointer.SetAt(test, test); 
    m_someClassRef->mfcMapAddress.SetAt(address, address); 
} 

MyClass에는 복사 생성자가 없지만 이것은 부적절하다고 생각했습니다. 또한 관련성이있는 경우 Visual Studio 6과 관련이 있습니다.

왜 이런 일이 벌어 질 수 있는지에 대한 아이디어가 있습니까?

감사합니다.

+4

어디에서 어떻게 m_someClassRef를 설정합니까? 내 추측은 그것이 null이라는 것이다. –

+0

별로 쉽지 않은데 두려워! 내 실제 디버깅 코드에서는 삽입을 수행하기 전에 실제로 맵의 크기를 얻습니다 (물론 모두 0입니다). 하나의 흥미로운 결과는 CMap이 완전히 초기화되지 않은 것처럼 보이므로 의도적으로 InitHashTable (, true)을 호출해야합니다. 내가이 일을하지 않으면, 제로 크래시에 의한 격차가 생깁니다. – John

+3

게시 된 코드에 문제가 없습니다 (적어도 충돌을 일으킬만한 것은 없습니다). 버그가 다른 곳에서 코드를 게시합니다. – john

답변

0

호기심이 많은 사람들에게 : 문제는 응용 프로그램 내의 다른 곳에서 memset이 SomeClass 인스턴스에서 호출되어 메모리를 초기화한다는 것입니다.

(memset을 알아 차리기 전에)이 문제점을 야기한 이유는 다음과 같습니다. 맵 멤버는 포인터가 아닌 일반 인스턴스 멤버이며 Map 멤버가 분명히 존재하지만 상태가 나쁜 매우 이상한 결과를 가져옵니다.

의견 덕분에 SomeClass지도 멤버를 대신 포인터 (예 : CMap * mfcMapAddress)로 변경하려고 시도했습니다. Lo와 보라, 심지어 내 생성자가 CMap 인스턴스를 생성 한 후에도 포인터 값은 0으로 닦여진다.

감사합니다.

+2

올바른 수정은 모든 것을 포인터로 변경하는 것이 아니므로주의 깊게 수동으로 메모리를 관리해야합니다. 즉, POD가 아닌 클래스를 초기화하는 끔찍한 방법 인'memset'을 제거해야합니다. 대신 생성자를 작성하고 올바르게 수정하십시오. –

+0

동의합니다. 이것은 RAII 관용구를 완전히 무너 뜨 렸고 효과적으로 나를 낭비하게 만들었습니다. 하지만 그 부분은 제가 불행히도 변경할 수있는 것이 아닙니다. – John

+0

memset에 대한 @ JonathanWakely의 조언을 마음에 받아 들여주세요. POD 이외에는 정의되지 않은 동작입니다. 당신은 확실히 CMap의 vtable 포인터를 원래의 선언문과 함께 삭제합니다. –