2016-04-03 22 views
1
  • kullanıcı kontrollü bellek havuzundan bir nesnenin örneğini (C++ 98 belki?)
  • Dinamik şeyleri kullanarak sistem havuzundan bellek ayrılamıyor yeni gibi, malloc
  • Ancak, yerleşik OS çağrıları, tarafımdan tanımlanan bir yığın dizisinden malloc'a kullanabilirim.
Ben

ayırma ve ben kullanıyorum C++ derleyicisi daha eski bir sürümü

class cBaseClass /* pure abstract */ 
{ 
public: 
virtual void ifFunc(void) = 0; 
virtual ~cBaseClass() = 0; 
} 

inline cBaseClass::~cBaseClass() 
{ 
} 

class cDclass:cBaseClass 
{ 
public: 
cDclass(); 
~cDclass(); 
void ifFunc(void); /* implement the pure virtual */ 
} 

cDclass::cDclass(void) 
{ 
printf("[0x%X] derived constructor called\n", this); 
} 
cDclass::~cDclass(void) 
{ 
printf("[0x%X] derived destructor called\n", this); 
} 
void cDclass::ifFunc(void) 
{ 
printf("[0x%X] ifFunc called from derived class\n", this); 
} 

uchar_t myHeap[4096]; 

int main (void) 
{ 
    cDclass* pMyPtr = NULL; 
    uint32_t i = 0; 
    (void) memset(myHeap, 0, sizeof(myHeap)/sizeof(myHeap[0]); 
    for(i = 0; i < 20; i++) 
    { 
     pMyPtr = myHeap[i * sizeof(cDclass) + 4]; 
     *pMyPtr = cDclass(); 
     pMyPtr->ifFunc(); /* Crash */   
    } 
} 

aşağıdakileri yapın girince ne görüyorum türetilmiş sınıfının yapıcı onun yıkıcı çağrılan called..then olur olduğunu bazı garip davranışları (program çöker) içine çalıştırıyorum

ve sonra bir çarpışma. * pMyPtr = cDclass() öğesinin bir sınıf oluşturduğuna ve daha sonra pMyPtr tarafından belirtilen adreste bu sınıfın bir kopyasını oluşturduğuna inanıyorum? Bunu söylüyorum çünkü pMyPtr = cDClass() 'u kaldırdığımda ve cDclass örneğini depolamak için bir taklit değişken oluşturup artık kilitlenmeyen memeliyi kullanın.

cevap

0
*pMyPtr = cDclass(); 

geçerli bir nesne zaten *pMyPtr mevcut olduğunu ve atama operatör kullanması varsayar. (Bu vptr kopyalamaz, çünkü tipik bir uygulaması, bu muhtemelen yeterince iyi değil.)

yerine ihtiyaç

new(pMyPtr) cDclass; 

belirli bir hafıza konumunda kurucusunu çağırmak için nedir. #include <new>'a ihtiyacınız olacak.

+0

Yerleşim yeni kullanmak için '' eklemeniz gerektiğinden emin değilim. –

+0

@DavidHaim '', Standard'ın operatörün yeni değerini (size_t, void *) 'belirttiği tek yerdir.Ve g ++ ve clang ++, herhangi bir başlık eklemeden kullanmaya çalışırsanız şikayet eder. – aschepler

0

ilk garip olan bu hat şu:

pMyPtr = myHeap[i * sizeof(cDclass) + 4]; 

şikayet etmeden derler. Bu uchar_t'u 'a dönüştürmek demektir, bu reinterpret_cast olmadan mümkün olmamalıdır. Ama derleyicinin orada daha yumuşak olması olabilir. Her neyse, en azından burada bir & operatörünü kaçırıyorsun.

İkinci problem, evet, varsayımınızda yanılıyorsunuz. Çizgide, yığın üzerinde geçici bir nesne oluşturulup, işaretçi konumunda zaten tamamen oluşturulmuş bir nesne olduğunu varsayalım, bu nesnenin derleyici tarafından oluşturulan kopya atama işlecini geçici olarak bir argüman olarak çağırın ve sonra geçici olarak yok edin.

Asla gerçekleşmeyen şey, bir nesnenin aslında bellekte oluşturulmuş olmasıdır. Bu, vptr'nin hiçbir zaman başlatılmadığı anlamına gelir, bu nedenle sanal işleve yapılan çağrı boş bir değerdir.

Yapmanız gereken, yerinde bir nesne oluşturmak için yerleşim yeni kullanmaktır. Sizin döngü aşağıdaki gibi görünmelidir: aslında oluşturduğunuz tüm nesneler için yıkıcı çağırmasını sorumlu olacak

int main (void) 
{ 
    uint32_t i = 0; 
    (void) memset(myHeap, 0, sizeof(myHeap)/sizeof(myHeap[0]); 
    for(i = 0; i < 20; i++) 
    { 
     // get the address to construct the object at 
     uchar_t* pMyAddr = &myHeap[i * sizeof(cDclass) + 4]; 
     // construct a new object in-place at that address 
     cDclass* pMyPtr = new (pMyAddr) cDclass(); 
     pMyPtr->ifFunc(); /* Don't crash */   
    } 
} 

Not.

+0

Yerleşim-yeni kullanmadan bunu yapmanın bir yolu var mı? örneğin cDClass yapabilirim temp = cDClass(); (void) memmove (pMyPtr, & temp, sizeof (temp)); Bu bir yerleştirmenin yeni ve mükemmel bir şekilde güvenli olması mıdır? Bu benim denediğim yaklaşım ve işe yaramış görünüyor ... ama tamamen güvenli olduğuna emin değilim. (Yerleştirme haberleri öncesinde insanlar ne yaptı?) – Jason

+0

Hayır, yapamazsınız. Yerleşim-yenisi budur. AFAIK, C++ 'nın başlangıcından bu yana oldukça kullanışlıdır, fakat erken C++ genel olarak garip tahsis ve yapıcı semantiği olmuştur. Neden yeni yerleşmeden kaçınmak istiyorsun? –

İlgili konular