星期二, 3月 10, 2009

[C/C++]placement new()

昨天有同事問到可不可以讓物件 new 在 share memory 裡面,我跟他說 c++ 的 new 可以像下面例子這樣用,但是他後來沒試。好吧,反正我以前也沒試過,就寫了個小程式試一下:
/**
* Filename: test_new.cpp
* Description: Test new(storage) Person();
*/
#include <cstdlib>
#include <string>
#include <iostream>

class Person {
public:
Person() {}
~Person() {}

std::string getName() { return _name; };
void setName( std::string name ) { _name=name; }

std::string toString() { return _name; }
private:
std::string _name;
};

int main( int argc, char* argv[] ) {
char* storage = (char*)malloc( 1024 ); // allocate 1K

Person* person = new(storage) Person();
person->setName( "anonymous" );
std::cout << person->toString() << std::endl;

// if just storage, person will be replaced by intArray. (2)
// int* intArray = new(storage) int[10];
int* intArray = new(storage+sizeof(person)) int[10];
int i=0;

// assign value.
for( i=0; i<10; i++ )
intArray[i] = i;

// show the values
for( i=0; i<10; i++ )
printf( "%d ", intArray[i]);
printf("\n");

// dump storage
char* iter=storage;
printf("=== begin dump ===\n");
i=0;
while( i!=512 ) {
printf( "%02x ", (unsigned char)*iter );
iter++;
i++;
if( !(i%16) )
printf( "\n" );
}
printf("=== end dump ===\n");

printf( "person address = %08x intArray address = %08x\n",
(unsigned int)person, (unsigned int)intArray );

// cannot delete, it cause segmentation fault. (1)
//delete person;
//delete[] intArray;

// but we can use free.
free( storage );
}


結論:
  1. new(storage) Person() 實際上是 new 在 storage 這塊空間裡面,所以之後如果呼叫 delete,會出錯。
  2. 如果不累加 storage 的話,會把之前配置的空間覆蓋掉。
  3. malloc() 可以用 shmget()、shmat() 代替,沒有問題。
  4. 以上面的例子,std::string 會配置一塊空間來放字串,這塊空間並不在 storage 裡面,使用時要注意。如果要這樣用,應該要再取代掉 STL allocator 的機制。

沒有留言: