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 03:24:47


Hi again,
----- Original Message -----
From: "vicente.botet" <vicente.botet_at_[hidden]>
To: <boost_at_[hidden]>
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_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?

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


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