返回   cpper编程论坛 > C/CPP/TMP/GP
注册账号 论坛帮助 会员列表 日历事件 搜索 今日新帖 标记版面已读

回复
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2006-03-05
pongba 的头像
高级会员
 
注册日期: 2004-09-02
帖子: 116
文章: 1
pongba 正向着好的方向发展
发送 MSN 消息给 pongba
默认 上次发到C++ news group上去的帖子,关于new/delete的问题,没有得到我想要的答案,翻出来大伙再讨论讨论

关键是我想知道背后的rationale,D&E上我记得没说。news group上的fellows一个劲的说不着调的话。我把帖子贴在下面,这个问题跟Pola上次发的自定义类相关new/delete代码有些关系,大伙说说看法

Why the inconsistent form of operator new/delete overloading?
« 主题开始 « 前一页 9 个帖子中的第 1 个到第 9 个 后一页 » 主题结束 »

固定字体 - 可变宽字体


1
发件人: pon...@gmail.com - 查看个人资料
日期: 2006年2月26日(星期日) 下午7时54分
电子邮件: pon...@gmail.com
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 删除 | 报告滥用行为 | 查找此作者的帖子

As we all know, operator new()/new[]() can be overloaded and then
called in new-expression.
E.g. Suppose we have some sort of Fast Memory Pool, we could sketch
something like this:

void* operator new(size_t, FastMemory&);

void operator delete(void*,FastMemory&);

the usage of the overloaded new above would of course be:

px = new (fast_mem) X;

but then I got stucked on trying to use the seamingly absolutely
natural way to delete px, that is:

delete (fast_mem) px; // Here! Error Occurs!

So why is this? And what's the alternative?
Of course, I really wanna know the rationale behind this language rule,
I would really appreciate your help, thanks in advance

--
Regards!

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复


2
发件人: Thomas Richter - 查看个人资料
日期: 2006年2月27日(星期一) 上午12时44分
电子邮件: Thomas Richter <t...@math.tu-berlin.de>
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

- 隐藏被引用文字 -
- 显示引用的文字 -
pon...@gmail.com wrote:
> As we all know, operator new()/new[]() can be overloaded and then
> called in new-expression.
> E.g. Suppose we have some sort of Fast Memory Pool, we could sketch
> something like this:

> void* operator new(size_t, FastMemory&);

> void operator delete(void*,FastMemory&);

> the usage of the overloaded new above would of course be:

> px = new (fast_mem) X;

> but then I got stucked on trying to use the seamingly absolutely
> natural way to delete px, that is:

> delete (fast_mem) px; // Here! Error Occurs!

Which is invalid. The corresponding delete operation is

delete px;

and it the job of your operator delete() to find and fetch the memory
pool the class has been allocated from. That is, you *must* overload
operator delete(void *) plus its array form. The other operator delete
is the "placement form" and it is only used if the constructor of an
object calls the placement new operator and then fails to construct the
object up to the end, in which case the corresponding operator delete
will delete the left-over memory.

> So why is this?

operator new(size_t, mem)

was originally intended to "place" objects into already allocated memory
where this memory is passed as the second argument. Clearly, this memory
would normally not require deletion - you would call the destructor,
then throw the memory away in the same way you allocated it - outside
the scope of the operator new/delete mechanism.

> And what's the alternative?

Overload the placement new, and the regular delete operator. Within
operator new(x,y), allocate enough memory for the object and a pointer
to the memory pool, keep care of alignment. Within operator delete(),
fetch the pointer to the memory pool from the raw memory you got as
argument, then call the release function of the pool.

So long,
Thomas

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post: Text for clearing space


3
发件人: ker...@mail.ru - 查看个人资料
日期: 2006年2月27日(星期一) 上午12时43分
电子邮件: ker...@mail.ru
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

Yes, that's true - you cannot pass additional arguments to operator
delete. You should lookup you pool by object's address or save required
information, e.g:

void operator new(size_t s, FastMemory& m)
{
static const size_t ptr_size=sizeof(void*);
void* p=m.allocate(s+ptr_size);
reinterpret_cast<void*&>=&m;
return p+ptr_size;

}

void operator delete(void* p,size_t s)
{
static const size_t ptr_size=sizeof(void*);
FastMemory* m=reinterpret_cast<FastMemory*>;
m.deallocate(p-ptr_size,s+ptr_size);

}

So, each object allocated by FastMemory pool has that particular pool
stated just before object's memory region starts.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post: Text for clearing space


4
发件人: Jeffrey Schwab - 查看个人资料
日期: 2006年2月27日(星期一) 上午4时04分
电子邮件: Jeffrey Schwab <j...@schwabcenter.com>
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

ker...@mail.ru wrote:
> void operator new(size_t s, FastMemory& m)

The return type should be a pointer type, not void.

> {
> static const size_t ptr_size=sizeof(void*);
> void* p=m.allocate(s+ptr_size);
> reinterpret_cast<void*&>=&m;

What is the purpose of this cast?

> return p+ptr_size;

Adding a size_t to a void* should be a compile-time error, since void
does not have any size. This might work better:

return static_cast<char*>+ptr_size;

> }

> void operator delete(void* p,size_t s)
> {
> static const size_t ptr_size=sizeof(void*);
> FastMemory* m=reinterpret_cast<FastMemory*>;
> m.deallocate(p-ptr_size,s+ptr_size);

The FastMemory* m is a pointer, so instead of m., you'll have to use m->
here. Also, p-ptr_size should not work for the same reason p+ptr_size
does not work. You could ram something like this through the compiler:

m->deallocate(static_cast<char*>-ptr_size,s+ptr_size);

> }

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post: Text for clearing space


5
发件人: kanze - 查看个人资料
日期: 2006年2月27日(星期一) 下午7时20分
电子邮件: "kanze" <k...@gabi-soft.fr>
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

Jeffrey Schwab wrote:
> ker...@mail.ru wrote:

[...]

> > return p+ptr_size;
> Adding a size_t to a void* should be a compile-time error, since void
> does not have any size. This might work better:
> return static_cast<char*>+ptr_size;

This still leaves open the possibility (probability, on a 32 bit
machine) that the resulting pointer is not sufficiently aligned.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post: Text for clearing space


6
发件人: pon...@gmail.com - 查看个人资料
日期: 2006年2月27日(星期一) 下午10时00分
电子邮件: pon...@gmail.com
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 删除 | 报告滥用行为 | 查找此作者的帖子

ker...@mail.ru wrote:
> void operator delete(void* p,size_t s)
> {
> static const size_t ptr_size=sizeof(void*);
> FastMemory* m=reinterpret_cast<FastMemory*>;
> m.deallocate(p-ptr_size,s+ptr_size);
> }

I do not think this is the right way. How do you presume that all the
chunks passed to operator delete has the same book-keeping structure?
That is, if we now pass some regular allocated memory chunk to operator
delete, like this:

int* p = new int;
delete p; // of course p doesn't point somewhere in FastMemory area,
but the overloaded operator delete() above treats it as one, and try to
"reinterpret_cast<FastMemory*>(p-ptr_size)", how could this succeed as
long as p doesn't point somewhere in FastMemory pool?

In a word, I don't think this alternative is "the" alternative. And I
strongly hope to know why the language forbids the seemingly natural
way to do this(that is, delete (fastMem) p? Is there something we
don't know?

P.S. The second alternative is imperfect, too. It's highly
inconsistent.Don't you think?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复


7
发件人: RenjithMohan - 查看个人资料
日期: 2006年2月28日(星期二) 上午12时45分
电子邮件: "RenjithMohan" <renjithmo...@hotmail.com>
论坛: comp.lang.c++.moderated
跟帖发送至: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

pon...@gmail.com wrote:
>but then I got stucked on trying to use the seamingly absolutely
>natural way to delete px, that is:
>delete (fast_mem) px; // Here! Error Occurs!

Here the error occurs since there is no such thing as a placement
delete operator.
So in order to achieve this you will have to call the form of your
delete operator.But before that you are supposed to call the dtor of
the class

like this

px->~X; //call the dtor
X:perator delete(px, fast_mem);

This will really call your overloaded delete operator.
The code inside your delete operator is really implementation dependent
. It depends on how you want the pool to behave. Most probably you
would be just marking one of your allocated nodes as allocable rather
than giving it back to the memory manager of the OS.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post: Text for clearing space


8
发件人: Ron Natalie - 查看个人资料
日期: 2006年2月27日(星期一) 上午4时06分
电子邮件: Ron Natalie <r...@spamcop.net>
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

pon...@gmail.com wrote:
> but then I got stucked on trying to use the seamingly absolutely
> natural way to delete px, that is:

> delete (fast_mem) px; // Here! Error Occurs!

There's no such thing as a placement delete expression.
The only time the non-default deallocation function is
called is when an exception happens during object creation.

Your choices are either:

1. Make your default deallocation function smart enough
to notice stuff allocated with the placement new and do the
right thing.

2. Explicitly call the destuctor and do what ever you need
to delete "fast_mem" (possibly in a function):

template <class T> void DeleteFastMem(T* t) {
t->~T();
// reclaim t here.
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post: Text for clearing space


9
发件人: Kodt - 查看个人资料
日期: 2006年2月27日(星期一) 下午6时43分
电子邮件: "Kodt" <nickolay.mer...@gmail.com>
论坛: comp.lang.c++.moderated
Not yet rated
评级:
显示选项

回复 | 答复作者 | 转发 | 打印 | 显示个别帖子 | 显示原始邮件 | 报告滥用行为 | 查找此作者的帖子

- 隐藏被引用文字 -
- 显示引用的文字 -
pon...@gmail.com wrote:
> As we all know, operator new()/new[]() can be overloaded and then
> called in new-expression.
> E.g. Suppose we have some sort of Fast Memory Pool, we could sketch
> something like this:

> void* operator new(size_t, FastMemory&);

> void operator delete(void*,FastMemory&);

> the usage of the overloaded new above would of course be:

> px = new (fast_mem) X;

> but then I got stucked on trying to use the seamingly absolutely
> natural way to delete px, that is:

> delete (fast_mem) px; // Here! Error Occurs!

> So why is this? And what's the alternative?
> Of course, I really wanna know the rationale behind this language rule,
> I would really appreciate your help, thanks in advance

The alternative is to call destructor and operator delete separately:

template<class T> void delete_fastmem(FastMemory& fast_mem, T* ptr)
{
if(!ptr) return;
ptr->~T();
operator delete(ptr, fast_mem);

}

Another alternative is to assert that there is only one fast_mem in the
system, and overload operator new and delete for given class

class Some
{
public:
static void* operator new(size_t n) { return alloc_at_fastmem(n); }
static void operator delete(void* p) { free_at_fastmem; }
.......

};

that makes common forms of new/delete expressions to use your
allocator.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

回复 Rate this post:
__________________
C++的罗浮宫
http://blog.csdn.net/pongba
TopLanguage
http://groups.google.com/group/pongba
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #2 (permalink)  
旧 2006-03-06
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

说实话,我没看懂上面那些牛人的回答,不过ponda你的问题提得也不明白啊。按照我的猜想,你是不是想问:“为什么C++标准不提供一个方便的对应placement new的placement delete,它可以使用‘delete (pool) obj;’之类的语法?”

按照我的理解,C++没有提供这个机制的原因可能是觉得没有必要。设想这样的代码:
c++ 代码:
  1. void foo() {
  2.     char* pool =  new char&#91;sizeof(MyClass)];
  3.     MyClass obj = new (pool) MyClass();
  4.     delete (pool) obj; // 假定我们允许程序员这样做,当然得重载operator delete()
  5.     ...
  6. }

实际上这里的所谓"placement" delete实际上隐含了两个操作:首先,它调用obj->~MyClass()析构obj;其次,它应该调用free()释放pool指向的内存。可是问题来啦,作为这个"placement delete"的设计者,我哪知道传给我的void*该用什么销毁?没准那个buffer是用malloc()或者其他什么AllocatePage()申请的呢?这个时候程序员重载operator delete()的原型可能是这个样子的:
cpp 代码:
  1. void MyClass::operator delete(void* ptr, void* buffer)
  2. //姑且让我这么写吧,拿真正的operator delete()原型代替一下
  3. {
  4.     // 我凭什么来确定buffer指向的空间用什么释放?
  5. }

这时候即便是switch/case也用不上了,因为没有可供比较的依据(除非在某个特定的实现里可以用ptr的地址取值范围确定该用什么释放,不过这种办法肯定不保险。)

所以C++标准宁可不提供这种delete,以免因为delete operator管得太多让程序员没法用了。不知我说得对不对。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #3 (permalink)  
旧 2006-03-06
pongba 的头像
高级会员
 
注册日期: 2004-09-02
帖子: 116
文章: 1
pongba 正向着好的方向发展
发送 MSN 消息给 pongba
默认

引用:
作者: cppof286
说实话,我没看懂上面那些牛人的回答,不过ponda你的问题提得也不明白啊。按照我的猜想,你是不是想问:“为什么C++标准不提供一个方便的对应placement new的placement delete,它可以使用‘delete (pool) obj;’之类的语法?”

按照我的理解,C++没有提...
你说的都是对的。这也是我自己想的答案。我只是想看看guru们的答复而已,可惜他们都没有提到这些。只说应该怎么做

实际中如果要想写出泛型的代码,还是把申请内存跟构建对象分开来进行比较好,像vector那样
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #4 (permalink)  
旧 2006-03-06
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

看这个代码:
//划出一块1M大小的buffer
void* HeapZone = std::malloc(1024);

//申请
MyClass* ptr = new (HeapZone) MyClass;

//使用...

//回收
free(HeapZone);
和执行delete HeapZone相比,哪里不同呢?——dtor没有执行,但是内存全被回收了。
你可以在MyClass的dtor里打印些信息证明这一点。
所以delete (HeapZone)ptr的意义存在么?
delete本身存在这个语意。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #5 (permalink)  
旧 2006-03-06
Meta 的头像
版主
 
注册日期: 2004-12-02
帖子: 226
文章: 5
Meta 正向着好的方向发展
默认

这里所讨论的placement new和placement delete应当是全局的, 通用的.
placement new的语法:
void* new(size_t size, void* p);
placement new可以将对象构建在用户所指定的任意一块内存区域上(堆, 栈,...).

假设的placement delete语法:
void delete(void*p, void* mem);
placement delete, 不是不想提供, 而是无法提供. 编译器显然没有用户清楚该块内存的来历. 他拿到这块内存后, 问题在于如何释放? 传入的第二个参数, 根本没有告诉他除了地址以外的任何信息, 这一点和placement new完全不一样, 他只是接受一个已经构建好的内存区域的地址而已,自己不做分配的.
这就是通用placement的弊病, 既然你通用, 那就无法获取特定的信息. 只能让用户自己去进行这个动作.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #6 (permalink)  
旧 2006-03-06
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认

我觉得这本来就是Bjarne Stroustrup怪癖惹的祸。B.S.比较喜欢把原来的东西解释出新的意思,然后以此避免加入关键词。
本来new包含了两层语义,也就是所谓的operator new和new operator。前者分配内存,后者调用ctor。对于一个C++用户来说,他/她/它能够控制前者,但是不能控制后者。
其实直到这里,还是很正常的,但是后来有人说,C++里面,我无法直接调用ctor呀。为了满足这个要求,必须加入一个机制。但是直接调用ctor的语法和别的容易冲突,如果专门加一个新的语法要素,譬如说
ctor( SomeClass, p );// 相当于p->SomeClass::SomeClass()
B.S.会很不喜欢的。因此,最后加了一个placement new。placement new把new本身的语义脱离开了。也就是说,new的过程,不再是那么“自动”。

placement new之所以能够这样做,是因为它的上下文是可以控制的,说得更粗鲁一点,因为它本身“没责任”,也就是说,它不用确认这个内存是否合法,长度是否够,是否对齐,...。所以,我可以写一个函数,接受一个p作为参数,在这上面placement new一个新对象,然后返回,美其名曰为“in place factory”

为什么没有placement delete,因为从需要上来说,我们可以直接调用dtor,也就是说,对dtor的直接调用部分体现了placement delete。为什么无法实现placement delete呢?这我觉得分两种情况考虑。第一种就是这个指针的上下文是已知的,那么,我不需要placement delete也可以活下去,甚至活得不差。其次,如果这个上下文是未知的,我是不能像placement new那样不负责任的进行delete的,所以这种情况下,无意义。进一步的想,如果有placement delete,我们能够获得什么好处吗?不能,因为保持形式上一致最大的原因是for GP,但是这里形式上已经不一致了,GP不能用。

其实,如果ctor是可调用的,placement new也没什么意义的
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #7 (permalink)  
旧 2006-03-06
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

Bjarne是不是有怪癖我不知道,不过猫老大(现在是不是该改名叫骷髅猫老大?)的话我基本上同意。另外,我建议大家是不是可以想得再多一点:

1. 这个placement new在工程开发中能用在哪些地方?在我的印象里,除了在STL容器内部见过这个东西之外,我基本上没有在其它任何地方见过这个东西。大家能举出其他的例子么?

2. placement delete这个玩意到底在实际程序中有多少作用?按照经典的做法,placement delete的作用是在“placement new构造对象失败时自动调用”的,换句话说,它符合猫老大的“不能控制”一说,只是这时候我们不能控制的是free()或者::delete(),那么,我们可以保证自己编写的placement delete的合法性么?比如,为什么我们不能这样:

c++ 代码:
  1. ...
  2. MyClass* ptr = 0;
  3. Allocator allocator(...);
  4. try {
  5.     ptr = new(allocator) MyClass;
  6. } catch(...) {
  7.     allocator.deallocate_last_buffer(); // 释放最后一次分配的内存
  8. }

我倒觉得让程序员自己来保证访问的合法性比用placement delete更好一点。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #8 (permalink)  
旧 2006-03-06
bankrock 的头像
高级会员
 
注册日期: 2003-12-11
帖子: 847
文章: 7
bankrock 正向着好的方向发展
默认

回复太长,没耐心看完了。guru们说的好像也就是我们在另外一个帖子里讨论的东西。placement delete的功能:
代码:
The other operator delete is the "placement form" and it is only used if the constructor of an object calls the placement new operator and then fails to construct the object up to the end, in which case the corresponding operator delete will delete the left-over memory.
看起来太单薄了。如果如pora所说placement new/delete只是BS为了把operator new和ctor的调用分离而作,那么为什么要采取operator new(size_t, void*)这种形式呢?更好的办法是传入一个明确的类指针吧,很难想象有人要用ctor(someclass, void*)这种功能。void* operator new(size_t, someclass*)更合理些,或者void* operator new(size_t, MemPool<someclass>&)。前者没必要placement delete,后者的话还是有必要的(只是纸上谈兵一下,我也不知道有没有人会为了一个类实现mempool)。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #9 (permalink)  
旧 2006-03-07
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认

引用:
作者: bankrock
回复太长,没耐心看完了。guru们说的好像也就是我们在另外一个帖子里讨论的东西。placement delete的功能:
[code]The other operator delete
is the "placement form" and it is only used i...
其实你的那个new,形式不好当然,必须承认我的ctor那个例子,形式也不好。

你说的第二个情况,我通过直接调用dtor,也可以达到,只不过多一句话而已。

我偶尔会为特定类专门写pool的。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #10 (permalink)  
旧 2006-03-07
Samark 的头像
普通会员
 
注册日期: 2006-03-07
帖子: 84
Samark 正向着好的方向发展
默认

引用:
作者: cppof286
Bjarne是不是有怪癖我不知道,不过猫老大(现在是不是该改名叫骷髅猫老大?)的话我基本上同意。另外,我建议大家是不是可以想得再多一点:

1. 这个placement new在工程开发中能用在哪些地方?在我的印象里,除了在STL容器内部见过这个东西之外,我基本上没有在其它任何地方见过这个东...
很多UNIX基于单进程模型的单进程程序, 需要访问同一块共享内存, 这个时候在共享内存中构建高效的数据结构很必要, 如果要用STL那些, 需要自己写个allocator或者用inplace new
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #11 (permalink)  
旧 2006-03-07
Samark 的头像
普通会员
 
注册日期: 2006-03-07
帖子: 84
Samark 正向着好的方向发展
默认

实际上我还有些问题不明白,
void* HeapZone = std::malloc(1024);

MyClass* ptr1 = new (HeapZone) MyClass;
MyClass* ptr2 = new (HeapZone) MyClass;

这个ptr1跟ptr2的地址会一样, 也就是placement new并没有提供任何自动管理的机制, 还是需要自己来管理, 这样如果要实现一个如List的数据结构, 必需自己记录预先开辟的内存使用情况, 有谁读过STL allocator的源码? STL是怎么在指定的开辟好的内存上allcate多次内存并记录预先开辟内存的使用情况的?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #12 (permalink)  
旧 2006-03-08
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认

记录这些,不是std::allocator的责任,是使用者的责任。当然通常是不会出问题的。

p.s. 你最近如果去饭店,出门的时候要小心,不要怪我没提醒你
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #13 (permalink)  
旧 2006-03-08
Meta 的头像
版主
 
注册日期: 2004-12-02
帖子: 226
文章: 5
Meta 正向着好的方向发展
默认

引用:
作者: Samark
实际上我还有些问题不明白,
void* HeapZone = std::malloc(1024);

MyClass* ptr1 = new (HeapZone) MyClass;
MyClass* ptr2 = new (HeapZone) MyClass;

这个ptr1跟ptr2...
STL的allocator是通过free list来管理空闲的块的. 块的大小以8个bytes为单位, 最大是128的block, 最小是8个byte的. 应当有16个list.根据对象的大小来选择, 需要更大的内存就问memory pool要, 如果memory pool不够, 那就再问heap要.

你用placement new本来内存就要自己管理. 因为placement new接受的内存又未必只是heap的, 可以来自静态存储区, 或者一个stack. 这个placement new的就是个通用的, 能够对任意给你的内存区域进行初始化构建工作的. 但是这个内存的管理, 只有用户最清楚. 如果这个内存是static或者stack的, 你难道指望new和delete去给你自动管理?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #14 (permalink)  
旧 2006-03-08
Meta 的头像
版主
 
注册日期: 2004-12-02
帖子: 226
文章: 5
Meta 正向着好的方向发展
默认

引用:
作者: cppof286
1.这个placement new在工程开发中能用在哪些地方?在我的印象里,除了在STL容器内部见过这个东西之外,我基本上没有在其它任何地方见过这个东西。大家能举出其他的例子么?
在工程开发中还是很有用的, 至少偶碰到过. 就是为了避免所谓的内存泄漏(虽然我不是很赞同这种做法), 所有new出来的对象都是构建于某个heapObject上.你都不用管去delete这个对象. 你只要负责初始化和析构对象, 内存的事情, 完全不用你考虑. 但我觉得这种做法, 太浪费空间了.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #15 (permalink)  
旧 2006-03-08
cppof286 的头像
高级会员
 
注册日期: 2004-11-24
住址: 已经在北京了
帖子: 147
cppof286 正向着好的方向发展
发送 MSN 消息给 cppof286
默认

多谢Meta老大的解释。你这么一说我也想起来了。以前在看Open C++的实现,他们的做法大概就是这样,不过他们是用一个GC分配器来负责的。至于浪费空间么,我倒是觉得这是一个在内存不够用的情况下建立内存池的好办法,前提是对象个数必须确定。

但关键是第二个问题,因为我今年负责的是一个C++的静态安全分析项目,所以我必须向老板提交一个C++安全漏洞列表。我可以列出一大堆placement delete设计不当导致的程序错误,但是我没法给出一个“怎么写正确的placement delete”的指导(当然我也没有这个本事),所以拿来给大家讨论一下,大家有没有兴趣?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #16 (permalink)  
旧 2006-03-08
Samark 的头像
普通会员
 
注册日期: 2006-03-07
帖子: 84
Samark 正向着好的方向发展
默认

引用:
作者: Meta
STL的allocator是通过free list来管理空闲的块的. 块的大小以8个bytes为单位, 最大是128的block, 最小是8个byte的. 应当有16个list.根据对象的大小来选择, 需要更大的内存就问memory pool要, 如果memory pool不够, 那就再问heap要.

你用placement new本来内存就要自己管理. 因为placement new接受的内存又未必只是heap的, 可以来自静态存储区, 或者一个stack. 这个placement new的就是个通用的, 能够对任意给你的内存区域进行初始化构建工作的. 但是这个内存的管理, 只有用户最清楚. 如果这个内存是static或者stack的, 你难道指望new和delete去给你自动管理?
看了一下allocator的实现, 没做任何内存使用情况的实现, 直接调用了new delete, 把内存使用情况记录交给了操作系统。
如果要构建一个共享内存的Map, allocator还是要自己记录内存使用情况。 这一种应该可以提供一种统一的记录机制, 提供给allocator起始地址以及size, 然allocator来用自己的结构记录使用情况比较好,不知道有没有人实现过
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #17 (permalink)  
旧 2006-03-08
Meta 的头像
版主
 
注册日期: 2004-12-02
帖子: 226
文章: 5
Meta 正向着好的方向发展
默认

http://www.jjhou.com/tass/stl_alloc.h.html
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #18 (permalink)  
旧 2006-03-08
Samark 的头像
普通会员
 
注册日期: 2006-03-07
帖子: 84
Samark 正向着好的方向发展
默认

看了, 想偷懒自己不管内存是不行了
Digg this Post!