tag:blogger.com,1999:blog-5246987755651065286.post234937259101072762..comments2024-02-22T16:15:42.388-08:00Comments on cbloom rants: 11-06-12 - Using your own malloc with operator newcbloomhttp://www.blogger.com/profile/10714564834899413045noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-5246987755651065286.post-49610715837541417622012-11-12T10:37:23.809-08:002012-11-12T10:37:23.809-08:00You use something like :
template < typename ...You use something like :<br /><br /> template < typename t_type ><br /> static inline t_type * construct(t_type * pArray,const size_t size)<br /> {<br /> for(size_t i=0;i<size;i++)<br /> new (ePlacementNew, pArray+i) t_type;<br /> <br /> return pArray;<br /> }cbloomhttps://www.blogger.com/profile/10714564834899413045noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-51952130791343527542012-11-12T10:35:09.779-08:002012-11-12T10:35:09.779-08:00" new [], delete []? "
Assuming non-pol..." new [], delete []? "<br /><br />Assuming non-polymorphic, those are straightforward.<br /><br />It's up to you whether or not you want to shift the pointer and store the count before the head of the array. (that's needed if you want delete [] to work without passing in the count).<br /><br />Personally I don't do that, I pass in the size to MyDeleteArray().<br /><br />Actually I almost never new/delete arrays, if I have an array I just use some kind of template array container.<br />cbloomhttps://www.blogger.com/profile/10714564834899413045noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-48283998321503514862012-11-12T05:54:55.404-08:002012-11-12T05:54:55.404-08:00by the way (off topic) is there a way to get blogg...by the way (off topic) is there a way to get blogger to email you when somebody replies to you or comments on one of your blog posts?https://www.blogger.com/profile/07698332535766464476noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-43626477332955870732012-11-12T05:53:15.743-08:002012-11-12T05:53:15.743-08:00This comment has been removed by the author.https://www.blogger.com/profile/07698332535766464476noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-80053939030662999542012-11-12T05:53:05.936-08:002012-11-12T05:53:05.936-08:00new [], delete []?new [], delete []?https://www.blogger.com/profile/07698332535766464476noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-91557657415027909952012-11-09T10:08:04.201-08:002012-11-09T10:08:04.201-08:00When no size is provided I do a hash table lookup,...When no size is provided I do a hash table lookup, so technically O(1), but yeah.<br /><br />I presume that small/non-polymorphic allocs are common (and should be fast and minimum overhead), and large/polymorphic are rare.<br /><br />Surely it would be better to just have two completely different allocators, one for small blocks and one for large/polymorphic, and make the caller use a totally different malloc/free pair for those two cases.<br /><br />In my personal code I like to do mallocs by reserving chunks of virtual address range, but I figured that was too messy in a library.<br />cbloomhttps://www.blogger.com/profile/10714564834899413045noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-30479108763632641642012-11-09T09:33:51.998-08:002012-11-09T09:33:51.998-08:00If you want to do any optimization of your allocat...If you want to do any optimization of your allocator based on passing in the block size on free, but you don't want to HAVE to pass in the block size on free, don't you need to call a different malloc depending on whether you will free it with the block size or not? Or are you sucking up an O(N) free in the no-size case?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-88168472917255545612012-11-07T11:51:43.027-08:002012-11-07T11:51:43.027-08:00Yeah it definitely fails with MI. The problem is ...Yeah it definitely fails with MI. The problem is you need to be able to find the base allocation pointer from any of the types in the class hierarchy.<br /><br />That didn't even occur to me cuz I just never use MI any more.<br /><br />I believe it's fundamentally impossible to fix without adding meta-language.<br /><br />The problem is when you are given a B* to free, there's nothing at compile-time that tells you that B* is a standalone object, or part of a multiple inheritance.<br /><br />It's easy to fix with meta-language. Two possibilities :<br /><br />1. Require that all polymorphic objects have a "get_base" virtual member function that provides the allocation address.<br /><br />2. Make MyDeleteVirtual take an extra template parameter in which the caller explicitly specifies the base type.<br /><br />3. The only time I've used MI in a large code base, we required that every polymorphic MI class derive from a virtual base Root class, so that you could always cast to Root to get a consistent address for an object.<br /><br />4. When the destructors run, make them register their pointer on a stack.<br /><br />5. (abusing the language) You should be able to grab the address of the destructor from your vtable and thus find your most-derived type.<br /><br />It would be nice to at least detect MI at runtime and assert. (the underlying allocator can probably do this)<br />cbloomhttps://www.blogger.com/profile/10714564834899413045noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-26671329942830140842012-11-07T11:00:55.816-08:002012-11-07T11:00:55.816-08:00If it really fails with MI, can you add a static_a...If it really fails with MI, can you add a static_assert to detect MI use?Cathttps://www.blogger.com/profile/14195874651352683585noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-36953960036802152442012-11-07T10:18:26.412-08:002012-11-07T10:18:26.412-08:00dynamic_cast was meant to be dynamic_cast < voi...dynamic_cast was meant to be dynamic_cast < void* >Arseny Kapoulkinehttps://www.blogger.com/profile/18310595345818946666noreply@blogger.comtag:blogger.com,1999:blog-5246987755651065286.post-50795269219815059562012-11-07T10:17:44.484-08:002012-11-07T10:17:44.484-08:00This does not work with multiple inheritance, i.e....This does not work with multiple inheritance, i.e.<br /><br />struct A { virtual ~A() {} char a; };<br />struct B { virtual ~B() {} char b; };<br />struct C: A, B { };<br /><br />B* b = MyNew(C)();<br />MyFree(b);<br /><br />As far as I know, unless you have RTTI and are willing to use dynamic_cast (ugh), you have to resort to overriding the operator delete, locally (inside the class) or globally. For global overrides, at one company we used a complicated system to be able to specify a per-allocation pool (i.e. MyNew(pool, type) + MyDelete(pool, ptr)) - it stored the pool pointer on a thread-local deallocation stack and then called the global operator delete, which inspected the stack to get the pool pointer (the stack is needed since MyDelete operations can cascade in case they are called from the dtor).<br /><br />God, I hate C++.Arseny Kapoulkinehttps://www.blogger.com/profile/18310595345818946666noreply@blogger.com