
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of vicente.botet Sent: Thursday, October 15, 2009 3:25 AM To: boost@lists.boost.org Subject: Re: [boost] How to get the size of an C-array?
Hi again, ----- Original Message ----- From: "vicente.botet" <vicente.botet@wanadoo.fr> To: <boost@lists.boost.org> Sent: Thursday, October 15, 2009 8:18 AM Subject: Re: [boost] How to get the size of an C-array?
Hi, ----- Original Message ----- From: "Schrader, Glenn" <gschrad@ll.mit.edu> To: <boost@lists.boost.org> Sent: Wednesday, October 14, 2009 11:43 PM Subject: Re: [boost] How to get the size of an C-array?
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-
On Behalf Of vicente.botet Sent: Wednesday, October 14, 2009 4:54 PM To: boost@lists.boost.org Subject: Re: [boost] How to get the size of an C-array?
Hi Andrey, ----- Original Message ----- From: "Andrey Semashev" <andrey.semashev@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, October 14, 2009 7:18 PM Subject: Re: [boost] How to get the size of an C-array?
vicente.botet wrote:
Hi,
On TBoost.STM, I need to do something before deleting an array on
T* ptr = new T[3];
// in another file, the number of elements to which ptr points is
unknown.
// before deleting for (size_t i=0; i< 'ptr size'; ++i) { // do something with &ptr[i] } delete [] ptr;
As the number of elemenst is unknow in the separated unit, I have no mean to iterate on ptr to get the address of the elements.
The C++ compiler or the C++ standard library knows this number of elements as it needs to call the destructor of each element when deleting
each one of the elements of the array, or more precissely with the address of each one of the elements. the pointer. Is there something in Boost or a portable way to recover
number of elements of the array, maybe overloading the new [] operator and prefixing the allocate storage with some information? But what information can be stored so the implementation is portable?
There is no portable way to acquire the dynamic array length. IMO,
are two practical solutions for this:
1. Put everything you need into T's destructor. If T is a third
type then a wrapper class around T can serve the purpose.
Well, the problem is that we need to do something before the destructor is called. When deleting an array of transactional objects we need to mark each one of the elements as if they were written, so the conclict detection cat detect other threads been written on a specific array element.
2. Use a range wrapper instead of a raw pointer to the array.
This is equivalent to say that we can not use dynamic arrays with the STM library. Before to abandoning I want to explore all the posibilities.
Regarding the trick with the prepended length storing, it can solve
problem, but it introduces pointer magic which may not be obvious for the ones reading the code (including yourself a couple months later). And, AFAIK, you won't be able to override the standard new and delete operators to behave that way, so you'll have to use dedicated functions to allocate/deallocate such arrays. Therefore I wouldn't recommend it unless there are significant reasons for it.
No, I don't want to overload the standard new and delete operators, just provide a mixing helping the user to define transactional objects. For these transactional objects, the overload of the operator new and new[] could set some information that will allow us to define a free function size taking a transactional object pointer and returning its size. The drawback of using specific functions is that we will need to educate
user, and yet more important, we couldn't use generic classes that make use of these standard operators, as e.g. auto_ptr or scoped_ptr.
The problem I find overloading new[] is that I dont know where my
information will be placed respect to the returned pointer, as the standard, prefix it already to store its own specific information.
pointer returned by new[] | v | my_prefic | std prefix | user area |
The parameter size_t of the new[] operator is the addition of sizes of std prefix and the user area.
While writing these lines, I think that maybe the size of std prefix can be calculated requesting the creation of an array with only one element, so we can calculate the
sizeof(std prefix) = requested size for new T[1] - sizeof(T)
Does this make sens? Would this be portable?
Somehow, you need to guarantee that the memory address of the start of
memory area is aligned properly for objects of type T, otherwise all of
bounces@lists.boost.org] the there party the the prefixed the the
elements in the array will be misaligned. Different architectures often have different alignment requirements.
Yes, I must consider alignement.
Also, consider the following: { T v[3]; T* p=&v[0]; int s = size(p); // undefined behavior }
Very good observation. Unfortunately, I don't think I could do nothing in this case. Is there a way to check if a pointer has been allocated dynimically?
Well I suspect the answer is no.
In my opinion, this should be undefined behavior as it is the case for
T v[3]; T* p=&v[0]; delete p; // undefined behavior
In addition, I don't need to make public this function, as I need it only internally. Maybe I could do something similar to the boost::extent metafunction:
template <typename T, std::size_t N = 0> struct number_of_elements { ... };
but number_of_elements will work as boost::extent except when the result of extent is 0. In this case the metafunction suposse that the given pointer has been allocated with the overloaded new[]. If it is not the case the result will be undefined.
Do you consider that this metafunction is coherent?
Can someone in this list explain why the standard don't allows to recover the number of elements allocated by new[]? What is the deep reason?
Best regards, Vicente
I don't know why but the same thing shows up elsewhere. For instance I don't know of a way to query the size of a memory block that was allocated with malloc() either. Even so, this isn't a major problem since its easy enough to create smart pointers that store the extra information. That also avoids burdening the infrastructure with things that many people may not care about under the "you only pay for what you use" C/C++ mantra. Tacking extra information onto the front of an array like you're doing above can be made to work. In fact, some (most??) malloc() and free() implementations manage their heap memory in a similar manner (e.g. using linked lists of allocated blocks and free blocks). You might get a sense of how portably this can be done by looking through the GNU implementation of malloc and free and see what they needed to do to support different platforms. There really isn't a safe way to do this using simple pointers so I use smart pointers quite a lot although in your case though I would also consider a std::vector. --glenn