2011-10-09 4 views
0

malloc으로 할당 된 객체에 vtable 포인터를 설정하는 컴파일러 독립적이고 구문 적으로 우아한 방법이 있습니까?VTable 포인터 및 malloc에 ​​

방출을위한 충분한 시간이있을 때까지 메모리 관리자에서 메모리 위치를 유지하기 위해 void ptrs를 사용해야하는 필요에 따라 메모리 릴리즈의 흐름을 제어 할 수 있어야하므로 새로운 기능을 직접 사용할 수는 없습니다.

class AbstractData 
{ 
public: 
    AbstractData() {} 
    virtual ~AbstractData() {} 

protected: 
    virtual void SetData(int NewData) =0; 
    virtual int GetData() const =0; 
}; 

class ConcreteData : public AbstractData 
{ 
protected: 
    int Data; 

public: 
    ConcreteData() {} 
    ~ConcreteData() {} 

    void SetData(int NewData); 
    int GetData() const; 

}; 

void ConcreteData::SetData(int NewData) {Data=NewData;} 

int ConcreteData::GetData() const 
{return Data;} 

int main(int argc, char* argv[]) 
{ 
    int OBJ_NUMBER = 4; 
    ConcreteData* Test = (ConcreteData*)malloc(OBJ_NUMBER*sizeof(ConcreteData)); 

    if (!Test) 
     return -1;   

    for (int x = 0; x < OBJ_NUMBER; x++) 
     Test[x] = ConcreteData(); 

    Test[0]->GetData(); //Constructor was never called, vptr never initialized, crash 

    free(Test); 
    Test = NULL; 
} 

로컬 복사본에 초기화 된 vtable 포인터가 있기를 기대했지만 실제로는 그렇지 않습니다. 어디 있는지 알고 있다면 vptr의 오프셋에 대한 컴파일러 종속적 인 역 참조를 할 수 있다는 것을 알고 있지만이 솔루션은 컴파일러에 의존하고 많은 할당에서 사용하기에는 좋지 않습니다. 예 ++ 8.0

int main(int argc, char* argv[]) 
{ 
    int OBJ_NUMBER = 4; 
    ConcreteData* Test = (ConcreteData*)malloc(OBJ_NUMBER*sizeof(ConcreteData)); 

    if (!Test) 
     return -1;   

    ConcreteData StealVPtr(); 

    int* VPtr = *(int**)StealVPtr; 

    for (int x = 0; x < OBJ_NUMBER; x++) 
     *(int**)Test[x] = VPtr; 

    Test[0]->GetData(); //VPtr initialized in compiler dependent way 

    free(Test); 
    Test = NULL; 
} 

또는 MSVC와 함께 작동, 배치 새가 사용될 수 있지만, 다시 한번 구문이 우아 모양과 배열이 PTR 앞에 계산 추가 할 때 배열 소멸자와 유형의 문제를 상쇄가 발생할 수 있습니다.

int main(int argc, char* argv[]) 
{ 
    int OBJ_NUMBER = 4; 
    ConcreteData* Test = (ConcreteData*)malloc(OBJ_NUMBER*sizeof(ConcreteData)); 

    if (!Test) 
     return -1;   

    for (int x = 0; x < OBJ_NUMBER; x++) 
    { 
     if (!(ConcreteData* PlcTest = new(Test[x]) ConcreteData())) 
     { 
      free(Test); 
      Test = NULL; 
      return -1; 
     } 
    } 

    PlcTest[0]->GetData(); //Constructor was invoked and VPtr was initialized 

    for (int x = OBJ_NUMBER-1; x >= 0; x--) 
     PlcTest[x].~ConcreteData(); 

    PlcTest = NULL; 

    free(Test); 
    Test = NULL; 
} 

정말이게 malloc을 사용하는 객체에서 VTable ptr/call 생성자를 초기화하는 유일한 방법입니까?

+3

새 소리가 좋은 옵션입니다. 아마 당신은이 전략에 당신을 인도 한 것에 다시 한번 주목할 필요가 있습니다. –

+1

그것은 "WTF ??!?"라고 말하는 가장 좋고 정치적인 방법이어야합니다. 나중에 사용하기 위해 주목! –

+0

'c'태그가 지정 되었습니까? C는 새로운 클래스, 클래스, 퍼블릭, 가상 또는 보호 된, 또는 생성자 또는 소멸자에 대한 개념이 없다. 'malloc', ..., ...의 반환 값에 대한 캐스트가 필요하지 않습니다. – pmg

답변

0

세계 newdelete을 무시할 수 있다는 것을 알지 못할 수도 있습니다. 주의, 당신은 또한 new[]delete[]이 완료 여기

예를로 재정의해야 :

void * operator new(size_t size) 
{ 
    return super_malloc(size); 
} 
0

당신은 미리 할당 된 메모리에 클래스 인스턴스를 생성하기 위해 placement new operator를 사용할 수 있습니다.