Bug 29688 - resize initializes whole array
Summary: resize initializes whole array
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 3.3.5
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-02 13:17 UTC by Theo Bosman
Modified: 2006-11-14 00:53 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Theo Bosman 2006-11-02 13:17:52 UTC
in valarray.h I found that resize is always deleting the old array, reallocating a new array and initialize to the value specified. The text book (Stroustrup) indicates that only the newly allocated elements should be initialized. In my case the array size was not changed but the array reinitialized (bad code will be changed). I assume this has been corrected in later versions. I solved the problem by putting the "destroy" and "fill" inside the if block.
Regards,
Theo Bosman

  template <class _Tp>
    inline void
    valarray<_Tp>::resize (size_t __n, _Tp __c)
    {
      // This complication is so to make valarray<valarray<T> > work
      // even though it is not required by the standard.  Nobody should
      // be saying valarray<valarray<T> > anyway.  See the specs.

      __valarray_destroy_elements(_M_data, _M_data + _M_size);

      if (_M_size != __n)
	{
	  __valarray_release_memory(_M_data);
	  _M_size = __n;
	  _M_data = __valarray_get_storage<_Tp>(__n); 
	}
          __valarray_fill_construct(_M_data, _M_data + __n, __c);
    }
Comment 1 Paolo Carlini 2006-11-02 13:34:04 UTC
I do not have Stroustrup at hand, but certainly the ISO C++ Standard 2003, the real reference for our work (we are implementing it), says, in 26.3.2.7/9, that resize first changes the length of *this to sz and then assigns to each element the value of the second argument. It also says that the operation invalidates all pointers and references to elements in the array, thus, the meaning is clear and our implementation is 100% conforming.
Comment 2 Paolo Carlini 2006-11-02 13:51:44 UTC
The only possible change I can see, as an optimization, is using __valarray_fill instead of __valarray_destroy_elements and __valarray_fill_construct, when _M_size == __n. Let's ask Gaby...
Comment 3 Theo Bosman 2006-11-02 15:56:54 UTC
Subject: Re:  resize initializes whole array

There is no argument against the ISO standard, but to a non C/C++ programmer 
it seems a waist of time to reallocate the array and initialize it when one 
wants to add something to an array. Some other compilers will copy the 
existing data into the newly allocated space which seems more in line with 
the text book.
The application will be changed to avoid the loss of data on a resize of 
arrays, which is a better idea anyway. Thanks for the speedy reply.
Theo Bosman

----- Original Message ----- 
From: "pcarlini at suse dot de" <gcc-bugzilla@gcc.gnu.org>
To: <theo.bosman@net.HCC.nl>
Sent: Thursday, November 02, 2006 2:51 PM
Subject: [Bug libstdc++/29688] resize initializes whole array


>
>
> ------- Comment #2 from pcarlini at suse dot de  2006-11-02 13:51 -------
> The only possible change I can see, as an optimization, is using
> __valarray_fill instead of __valarray_destroy_elements and
> __valarray_fill_construct, when _M_size == __n. Let's ask Gaby...
>
>
> -- 
>
> pcarlini at suse dot de changed:
>
>           What    |Removed                     |Added
> ----------------------------------------------------------------------------
>                 CC|                            |pcarlini at suse dot de, 
> gdr
>                   |                            |at integrable-solutions 
> dot
>                   |                            |net
>             Status|RESOLVED                    |UNCONFIRMED
>         Resolution|INVALID                     |
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29688
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
>
> 


Comment 4 Paolo Carlini 2006-11-03 00:08:19 UTC
(In reply to comment #3)
> Subject: Re:  resize initializes whole array
> 
> There is no argument against the ISO standard, but to a non C/C++ programmer 
> it seems a waist of time to reallocate the array and initialize it when one 
> wants to add something to an array. Some other compilers will copy the 
> existing data into the newly allocated space which seems more in line with 
> the text book.

I don't know. We are definitely implementing the ISO C++ Standard, and, by the way, many details in Stroustrup' books, predating the Standard, are know to be slightly different. I will also add that valarray is *very* special - its design was motivated by considerations of highest performance on superscalar architectures, etc. - for example vector::resize behaves in a completely different way, which probably you like better.

> The application will be changed to avoid the loss of data on a resize of 
> arrays, which is a better idea anyway. Thanks for the speedy reply.

For portability, that is the safe thing to do, yes, I agree.
Comment 5 David Fang 2006-11-03 07:28:55 UTC
> There is no argument against the ISO standard, but to a non C/C++ programmer 
> it seems a waist of time to reallocate the array and initialize it when one 
> wants to add something to an array. Some other compilers will copy the 
> existing data into the newly allocated space which seems more in line with 
> the text book.
> The application will be changed to avoid the loss of data on a resize of 
> arrays, which is a better idea anyway. Thanks for the speedy reply.

If you really want efficient appending to a dynamically allocated array, then use std::vector, which is capable of pre-allocating more memory than the number of elements, using the reserve() member function.  From looking in the implementation, N push_back operations result in lg N reallocations, by doubling the reserve size each time the capacity is exceeded.  vector achieves this by tracking three pointers: beginning, end-of-elements (size), end-of-storage (capacity).  valarray is lighter-weight, having only two pointers, beginning- and end-of-storage; thus it must reallocate upon resize (otherwise, how could size() be reported correctly?).  I'd only use valarray when the sizeof(container) is crucial and/or the size of the container is unlikely/infrequently to change at run-time.  
Comment 6 Paolo Carlini 2006-11-14 00:53:34 UTC
I have analized in detail the case at issue (resize to the same size of the current one) and came to the conclusion that trying to optimize for it (at the cost of increasing the size of the inlined function) isn't really worth the trouble, taking also into account that for PODs __valarray_destroy_elements is already optimized out.