2009-07-22 3 views
1

는 내가 객체를 생성하고 힙을 손상 객체 다루기는 다음과 같이 꽤 많이 내 응용 프로그램에서

disconnect() { 
    if (mVHTGlove) 
    delete mVHTGlove; 
} 

을 이 호출은 항상 다음 메시지와 함께 중단 점을 트리거합니다.

에서 중단 점이 트리거되었습니다. Des ignerDynD.exe.

이것은 DesignerDynD.exe 또는 로드 한 DLL 중 임의의 버그를 나타내는 힙의 손상에 기인 할 수있다.

DesignerDynD.exe 에 포커스가있는 동안 F12 키를 누름으로써 발생할 수 있습니다.

출력 창이 더 많은 진단 정보가있을 수 있습니다.

헤더 파일, lib 파일 및 dll 형태로만 제공되는 외부 라이브러리이므로 vhtGlove 클래스를 수정하여 스택 손상을 수정할 수 없습니다.

이 클래스를 깨끗하게 사용할 방법이 있습니까?


**** 편집 ::: 내가 그러나 내가 여기 당신은 전체 코드가 ... 동일한 결과를 얻을, 최소한까지 일을 제거하기 위해 노력했다.

#include "vhandtk/vhtCyberGlove.h" 
#include "vhandtk/vhtIOConn.h" 
#include "vhandtk/vhtBaseException.h" 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    vhtCyberGlove* testGlove = NULL; 

    vhtIOConn gloveAddress("cyberglove", "localhost", "12345", "com1", "115200"); 
    try 
    { 
     testGlove = new vhtCyberGlove(&gloveAddress,false); 

     if (testGlove->connect()) 
     cout << "Glove connected successfully" << endl; 
     else 
     { 
     throw vhtBaseException("testGlove()->connect() returned false."); 
     } 

     if (testGlove->disconnect()) 
     { 
     cout << "Glove disconnected successfully" << endl; 
     } 
     else 
     { 
     throw vhtBaseException("testGlove()->disconnect() returned false."); 
     } 

    } 
    catch (vhtBaseException *e) 
    { 
     cout << "Error with gloves: " << e << endl; 
     system("pause"); 
     exit(0); 
    } 

    delete testGlove; 

    return 0; 
} 

장갑을 삭제할 때 여전히 충돌합니다.


편집 # 2 : 난 그냥 할당과도 충돌 vhtCyberGlove의 인스턴스를 삭제합니다.

int main(int argc, char* argv[]) 
{ 
    vhtCyberGlove* testGlove = NULL; 
    vhtIOConn gloveAddress("cyberglove", "localhost", "12345", "com1", "115200"); 
    testGlove = new vhtCyberGlove(&gloveAddress,false); 
    delete testGlove; //<<crash! 
    return 0; 
} 

아이디어가 있으십니까?

감사합니다.

JC

+3

_mVHTGlove_가 _NULL_이 아닌지 확인하실 필요가 없습니다. _delete_에 _NULL_ 포인터를 전달하는 것이 잘 정의되어 있습니다. – sbi

+0

disconnect()가 몇 번 호출 되었습니까? – MSN

+0

한 번만. . – levesque

답변

4

하나의 가능성은 mVHTGlove가 0으로 초기화되지 않는다는 것입니다. 연결이 호출되지 않은 채로 연결이 끊긴 경우 가비지 포인터를 할당 해제하려고 시도하게됩니다. 팔.

또 다른 가능성은 그 시점 이전에 실제로 스택을 손상시키고 있지만 손상으로 인해 실제로 충돌이 발생하는 것입니다.좋은 방법은 가능한 한 많은 코드를 주석 처리하고 여전히 실행되도록 프로그램을 작성한 다음 손상 여부를 확인하는 것입니다. 그렇지 않다면 천천히 코드가 돌아올 때까지 천천히 다시 가져와야합니다.


몇 가지 추가 생각 (수정 후).

API를 수동으로 "새"및 "삭제"할 필요없이 메모리 관리를위한 자체 호출이 없는지 확인하고 볼 수 있습니다. 이 말을하는 이유는 일부 DLL은 일부 메모리가 DLL 내부와 일부 외부에서 관리 될 때 이와 비슷한 모습을 보이는 문제를 겪어 왔기 때문입니다.

+0

이 모듈을 엄격하게 테스트하기 위해 응용 프로그램을 제거했습니다. 그래도 고마워. – levesque

2

vhtGlove이 삭제 될 때 힙 손상 오류가보고됩니다. 그러나 부패의 원인이되는 코드 자체가있을 수 있습니다. 이것은 종종 malloc에 대한 호출에서 힙에 할당 된 버퍼를 덮어 써서 발생합니다. 또는 같은 개체를 두 번 삭제하는 것일 수도 있습니다. std::auto_ptr과 같은 스마트 포인터를 사용하여 개체에 대한 포인터를 저장하면이 문제를 피할 수 있습니다.

+0

EDIT # 2를 참조하십시오. – levesque

1

손상 소스를 추적하려면 VisualSudio의 "메모리"창을 사용하여 mVHTGlove이 가리키는 메모리 위치를 살펴야합니다. 그 메모리에서 버퍼를 오버런시킨 것처럼 보일만한 것이 보이는 것이 있는지보십시오. 예를 들어, 프로그램의 다른 곳에서 사용 된 문자열이 보이면 해당 문자열을 조작하는 코드를 검토하십시오. 버퍼를 초과 할 수 있습니다.

1

vhtCyberGlove의 구현이 다른 DLL에 있다고 가정 할 때 힙이 일치하지 않을 수 있습니다. 예를 들어, VS에서 EXE가 디버그 CRT에 연결되어있는 동안 DLL이 출시 CRT에 연결되어있는 경우이 문제가 발생합니다. 이 경우 각 모듈은 다른 힙을 사용하고 잘못된 힙을 사용하여 메모리를 해제하려고하면 충돌이 발생합니다.

당신의 경우에는 vhtCyberGlove가 다른 DLL에 할당 된 일부 항목을 가져올 수 있지만 vhtCyberGlove 인스턴스를 삭제하면 항목이 직접 삭제되고 즉 DLL 대신 힙을 참조 할 수 있습니다. 그리고 다른 힙을 가리키는 포인터를 해제하려고 할 때, 효과적으로 힙을 손상시킵니다.

이 실제로 경우라면

자세한 내용은없이 나는이 수정 사항을 제공 할 수 있습니다 :
  1. 이 EXE는 DLL과 같은 힙을 사용해야합니다. 이
  2. 가 제대로 메모리 사용을 관리 할 수 ​​vhtCyberGlove의 프로 바이더를 가져 갈 수있는 가장 좋은 방법이 아니다 그래서 아마 당신은에 로컬 vhtIOConn의 주소를 전달하는 ..., 릴리스 모드에서
+0

답장을 보내 주셔서 감사합니다. True가 있습니다. 내 앱이 MSVCRT90D에 링크하는 동안 vhtCyberGlove 링크가 MSVCRT에 연결됩니다 (당연히 디버그에서 실행 중이므로). 그러나 이것이 얼마나 중요한지는 잘 모르겠습니다. 디버그 모드 응용 프로그램에 링크 된 릴리스 버전에서 많은 libs를 사용했는데 특별한 문제가 전혀 발생하지 않았으므로 선택한 코드를 디버그 할 수 없었습니다. 왜 지금과 다를 것입니까? – levesque

+0

이것은 vhtCyberGlove에 따라 다릅니다. 먼저 릴리스 모드에서 해당 코드를 시험해보고 문제가 사라 졌는지 확인하십시오. 그럴 경우 그 이유가 있습니다. 더 많은 코드를 보지 않고 말하기는 어렵지만 헤더 파일을 잘 살펴볼 것입니다. 함수 정의가 포함되어 있으면 해당 코드에서 (디버그) 힙을 사용하게됩니다. c'tor가 모두 DLL에 있고 일부 메모리를 할당하고 도르가 헤더에 있고 메모리를 비우려고하면 충돌이 발생합니다. 그렇다면 vhtCyberGlove의 공급자에 대한 잘못된 프로그래밍 일뿐입니다. 좋은 API는 이런 일이 발생하지 않도록해야합니다. 그리고 지금까지는 운이 좋았을 것입니다. – eran

1

당신을 잠급니다 건설자. 개체가이 포인터의 소유권을 가정하고 소멸자에서 삭제하려고 할 가능성이 있습니까?

+0

vhtIOConn을 동적으로 할당하고 생성자에 대한 포인터를 전달하려고했지만 도움이되지 않습니다. 또한 vhtIOConn 객체에서도 동일한 문제가 발생합니다. 방금 만든 후 줄을 지우면 bam crash. – levesque

+0

그런 다음 그것을 좁 힙니다. 서로 다른 두 개의 힙 소리가 그 가능성있는 대답입니다. –

관련 문제