1

C++에서 클래스를 선택하여 가상 상속을 사용하고 있습니다. 현재 파괴되고있다. Visual Studio에서 실행하면 온라인 컴파일러에서 제대로 컴파일 된 것처럼 보이지만 충돌이 발생합니다.Visual C++에서 가상 상속 계층 구조와 함께 사용하면 배치가 중단됨

필자는 순수 가상 기본 클래스를 가지고 있습니다.이 가상 클래스는 구현에 의해 사실상 상속됩니다. 그런 다음 구현 클래스를 상속하는 세 번째 클래스가 있습니다. 메모리 생성 및 해제를위한 내부 시스템을 사용하고 있습니다. 후드 아래 정렬 된 malloc으로 새로운 배치를 사용하고 있습니다. 그런 다음 자유를 사용하여 메모리를 비 웁니다. 나는이 최소한의 예를 창조했다. 내가하는 일이 정확히는 아니지만 비슷한 문제가있는 것 같습니다.

내가 말했듯이이 예제는 온라인 컴파일러에서 "완료"를 인쇄합니다. 그러나 Visual Studio 2015에서는 박쥐 개체에서 자유롭게 충돌하는 것으로 보입니다. 나는 가상의 상속과 새로운 배치에 상당히 익숙하다. 누구든지 문제가 보이나요?

+0

@Barry http://cpp.sh/2vd4t는 Visual Studio에서 붙여 넣기에 문제가 있습니다. 다음은 사용할 수있는 온라인 웹 사이트입니다 : http://webcompiler.cloudapp.net/. 거의 모든 내 질문에이 답변을 많이 볼 수 있습니다. 아마 내가 누락 된 부분을 지적하여 미래에 향상시킬 수 있을까요? – marsh

+2

코드에 대한 링크 게시는 권장하지 않습니다. 질문 자체에 코드를 게시하십시오. –

+3

@jeff 그는 배치 새로운 구문을 사용하고 있습니다. 그래서 malloc은 단지 원시 메모리를 할당합니다; new는 그것을 C++ 객체로 초기화합니다. 그렇다면 그는 명시 적으로 소멸자를 호출하고 무료로 전화하고 있습니다. 이것은 합법적입니다. 파생 클래스는 하나의 클래스에서 상속받을 때 항상 가상 소멸자를 갖습니다. –

답변

3

mallocAnimal*조정 주소로 신선한 메모리 주소, operator new 장소 그 주소에서 Bat 및 변환을 반환합니다. 이제 bat 변수는 malloc 블록의 어딘가를 가리 킵니다. free 불가능합니다.

Bat* bat0 = new(malloc(sizeof(Bat))) Bat; 
Animal* bat = bat0; 
std::cout << bat0 << " " << bat << "\n"; 

gcc 인쇄 두 개의 동일한 주소, 동안 VC++ 인쇄 서로 다른 두 사람. 다중 상속이 관련되지 않은 경우에도 두 동작 모두 완벽하게 정상이며 표준에서 허용됩니다. 대부분의 컴파일러는 실제로 단일 상속으로 주소를 조정하지 않지만 몇 가지 예외가 있습니다.

안전한쪽에 있으려면 동일한 두 주소에 의존하지 마십시오.

void* 동적 전송하여 원래의 어드레스를 복구 할 수있다 :

free(dynamic_cast<void*>(bat)); 

가 OK이어야한다. 물론 동적 캐스팅이 작동하려면 가상 함수가 필요합니다.

업데이트 : dynamic_cast<void*> 초기 포인터, 를 복구하지만 free 여전히 VC++와 충돌합니다. 나는 이유를 모른다. 모든 년 후, DLL이있는 경우

하여 C에서 타사 메모리 관리자를 통합하는 올바른 방법은 ++ 프로그램 (프로그램에있는 한 C++ 파일에 operator newoperator delete

void* ::operator new(size_t sz) { return my_managed_malloc(sz); } 
void ::operator delete (void* ptr) { return my_managed_free(ptr); } 

장소 이러한 과부하하는 것입니다 DLL)를 사용하고 잘못 정의 된 포인터 트릭없이 C++를 정상적으로 사용할 수 있습니다.

자세한 내용은 http://en.cppreference.com/w/cpp/memory/new/operator_new을 참조하십시오.

+0

대단히 감사합니다. 나는 CreateAnimal()과 DestroyAnimal()을 팩토리 함수로 사용하는 코드베이스를 상속하고있다. 기존 시스템을 작동시키는 방법이 있습니까? 내 경우에 동물은 순수 가상 클래스이며 각 구현은 사용자로부터 완전히 숨겨져 있으므로 CreateBat() 함수를 가질 수 없습니다. 적절한 malloc 포인터에 대한 참조를 내부적으로 보유해야합니까? 내가 잘못된 주소를 가지고 있기 때문에 올바른 유형의 캐스트가 작동하지 않는다고 가정하면 맞습니까? – marsh

+0

왜 전화를 걸면 값이 다시 조정되지 않습니까? 마치 내가 보통의 새로운 전화를 사용했던 것처럼? – marsh

+0

@marsh 업데이트를 참조하십시오. –