Boost logo

Boost :

Subject: Re: [boost] How to get the size of an C-array?
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2009-10-15 02:18:45


Hi,
----- Original Message -----
From: "Schrader, Glenn" <gschrad_at_[hidden]>
To: <boost_at_[hidden]>
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_at_[hidden] [mailto:boost-bounces_at_[hidden]]
>> On Behalf Of vicente.botet
>> Sent: Wednesday, October 14, 2009 4:54 PM
>> To: boost_at_[hidden]
>> Subject: Re: [boost] How to get the size of an C-array?
>>
>> Hi Andrey,
>> ----- Original Message -----
>> From: "Andrey Semashev" <andrey.semashev_at_[hidden]>
>> To: <boost_at_[hidden]>
>> 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 each
>> one of the elements of the array, or more precissely with the address of
>> each one of the elements.
>> >>
>> >> 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
>> the pointer. Is there something in Boost or a portable way to recover the
>> 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, there
>> > are two practical solutions for this:
>> >
>> > 1. Put everything you need into T's destructor. If T is a third party
>> > 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 the
>> > 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 the
>> 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 prefixed
>> 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 the
> memory area is aligned properly for objects of type T, otherwise all of 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?

Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk