From: Alexander Grigoriev on
I suppose VC6's vector<bool> doesn't compress bool to bits, otherwise, it
would not be able to use bool* (or any pointer) as iterator type.

"Igor Tandetnik" <itandetnik(a)mvps.org> wrote in message
news:ejWBQoqcKHA.4780(a)TK2MSFTNGP04.phx.gbl...
"aslan" <aslanski2002(a)yahoo.com> wrote in message
news:%23obrfjqcKHA.1028(a)TK2MSFTNGP06.phx.gbl...
> It doesn't create any problem with the VC6 and runs OK. Yes it's weird but
> believe it or not, memset doesn't write any random memory.

How do you determine that?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily
a good idea. It is hard to be sure where they are going to land, and it
could be dangerous sitting under them as they fly overhead. -- RFC 1925


From: aslan on

"Igor Tandetnik" <itandetnik(a)mvps.org>, iletisinde �unu yazd�,
news:eOAp$HrcKHA.1640(a)TK2MSFTNGP06.phx.gbl...
aslan <aslanski2002(a)yahoo.com> wrote:
> "Igor Tandetnik" <itandetnik(a)mvps.org>, iletisinde �unu yazd�,
> news:ejWBQoqcKHA.4780(a)TK2MSFTNGP04.phx.gbl...
> "aslan" <aslanski2002(a)yahoo.com> wrote in message
> news:%23obrfjqcKHA.1028(a)TK2MSFTNGP06.phx.gbl...
>> It doesn't create any problem with the VC6 and runs OK. Yes it's
>> weird but believe it or not, memset doesn't write any random memory.
>
> How do you determine that?
>
> *** aslan *** Using debugger's memory window (I'm talking about
> VC++6).

Well, this way you see that some memory is being written to. How do you know
that this memory is actually properly allocated and owned by the vector
object? After all, if you just take an uninitialized pointer and memset to
it, then the memory window will show that the memory pointed to by this
pointer is in fact initialized - but that doesn't make the program valid.

*** aslan ***

OK it's a wrong way. I should't have used std::vector<bool> there. I am only
answering your question "how do you know..." :

By stepping into the reserve() function which ends up by calling malloc with
the specified size. So you have one big chunk of memory on which you can
call resize() as many times as possible without any reallocation occurring
provided that you don't resize() with a bigger size than reserve() has
already allocated.

static void* allocate(size_t __n)
{
void* __result = malloc(__n);
if (0 == __result) __result = _S_oom_malloc(__n);
return __result;
}

--- which is called by_Alloc::allocate(size_t __n)
/* __n must be > 0 */
static void* allocate(size_t __n)
{
void* __ret = 0;

if (__n > (size_t) _MAX_BYTES) {
__ret = malloc_alloc::allocate(__n);
}
else {
_Obj* __STL_VOLATILE* __my_free_list
= _S_free_list + _S_freelist_index(__n);
// Acquire the lock here with a constructor call.
// This ensures that it is released in exit or during stack
// unwinding.
# ifndef _NOTHREADS
/*REFERENCED*/
_Lock __lock_instance;
# endif
_Obj* __RESTRICT __result = *__my_free_list;
if (__result == 0)
__ret = _S_refill(_S_round_up(__n));
else {
*__my_free_list = __result -> _M_free_list_link;
__ret = __result;
}
}

return __ret;
};

--- which is called by alloc::allocate(size_t __n)
template<class _Tp, class _Alloc>
class simple_alloc {

public:
static _Tp* allocate(size_t __n)
{ return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
static _Tp* allocate(void)
{ return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
static void deallocate(_Tp* __p, size_t __n)
{ if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
static void deallocate(_Tp* __p)
{ _Alloc::deallocate(__p, sizeof (_Tp)); }
};


--- which is called by _Vector_base::_M_allocate(size_t __n)
_Tp* _M_allocate(size_t __n)
{ return _M_data_allocator::allocate(__n); }


--- which is called by_Vector_base::_M_allocate_and_copy
iterator _M_allocate_and_copy(size_type __n, const_iterator __first,
const_iterator __last)
{
iterator __result = _M_allocate(__n);
__STL_TRY {
uninitialized_copy(__first, __last, __result);
return __result;
}
__STL_UNWIND(_M_deallocate(__result, __n));
}

--- which is called by_Vector_base::reserve(size_type __n)
void reserve(size_type __n) {
if (capacity() < __n) {
const size_type __old_size = size();
iterator __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp;
_M_finish = __tmp + __old_size;
_M_end_of_storage = _M_start + __n;
}
}



--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily
a good idea. It is hard to be sure where they are going to land, and it
could be dangerous sitting under them as they fly overhead. -- RFC 1925

From: aslan on

"Alexander Grigoriev" <alegr(a)earthlink.net>, iletisinde �unu yazd�,
news:eelmAwwcKHA.1640(a)TK2MSFTNGP06.phx.gbl...
>I suppose VC6's vector<bool> doesn't compress bool to bits, otherwise, it
>would not be able to use bool* (or any pointer) as iterator type.

Exactly. Type "bool" happens to be an 8-bit integer in VC6.

The following statement:
printf("sizeof(bool)=%d\n", sizeof(bool));

displays the following:
sizeof(bool)=1

>
> "Igor Tandetnik" <itandetnik(a)mvps.org> wrote in message
> news:ejWBQoqcKHA.4780(a)TK2MSFTNGP04.phx.gbl...
> "aslan" <aslanski2002(a)yahoo.com> wrote in message
> news:%23obrfjqcKHA.1028(a)TK2MSFTNGP06.phx.gbl...
>> It doesn't create any problem with the VC6 and runs OK. Yes it's weird
>> but
>> believe it or not, memset doesn't write any random memory.
>
> How do you determine that?
> --
> With best wishes,
> Igor Tandetnik
>
> With sufficient thrust, pigs fly just fine. However, this is not
> necessarily a good idea. It is hard to be sure where they are going to
> land, and it could be dangerous sitting under them as they fly
> overhead. -- RFC 1925
>
>

From: Ulrich Eckhardt on
aslan wrote:
> "Ulrich Eckhardt" <eckhardt(a)satorlaser.com>, iletisinde şunu yazdı,
> news:nfufu6-lht.ln1(a)satorlaser.homedns.org...
>> aslan wrote:
>>> The following code compiles (and runs) OK with VC++ 6.
>>>
>>> std::vector<bool> smallsieve;
>>>
>>> smallsieve.reserve(smsize+1);
>>>
>>> memset(smallsieve.begin(), true, smsize+1);
>>
>> Well, the code is broken in several ways:
>>
>> 1. An iterator is not a pointer.
> OK. Maybe it's my habit from VC++6. because it works with it (at least for
> std::vector<T>::begin()).
>
>> 2. reserve() doesn't change the number of elements in a vector, you mean
>> resize().
> No it's reserve(). Again it's OK with VC++6. Yeah right, it's bad. I need
> to change it.

Danger: reserve() allocates enough memory to store the given number of
elements, so you can add elements without the vector having to reallocate
memory. This does not change the size and it does not technically create
those elements or allow you to access them. Try this with VC6:

std::vector<bool> vec;
vec.reserve(2);
memset(smallsieve.begin(), true, 2);
bvec.push_back(false);
for(int i=0; i!=3; ++i)
std::cout << "vec[" << i << "]=" << vec[i] << std::endl;

You could also write a test class that gives you a message whenever it is
created, copied, assigned and destroyed and put that into a vector. You
could then actually see the difference between resize() and reserve().

Accessing them is what is called "undefined behaviour", which is standardese
for "you should have checked that yourself and all guarantees are off". You
are accessing these nonexistent elements using memset(). Since you are
probably never actually changing the size afterwards and the vector on its
own doesn't touch that memory, you never even notice.

BTW: I mentioned that you can actually use memset():

std::vector<T> vec;
vec.resize(n);
std::memset(&vec.front(), 0, vec.size()*sizeof(T));

This requires that 'T' is a POD, i.e. a type without any constructor,
virtual function etc. Builtin types, enumerations, unions and C-compatible
structures are such PODs.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: aslan on

"Ulrich Eckhardt" <eckhardt(a)satorlaser.com>, iletisinde şunu yazdı,
news:d9jhu6-05v.ln1(a)satorlaser.homedns.org...
> aslan wrote:
>> "Ulrich Eckhardt" <eckhardt(a)satorlaser.com>, iletisinde şunu yazdı,
>> news:nfufu6-lht.ln1(a)satorlaser.homedns.org...
>>> aslan wrote:
>>>> The following code compiles (and runs) OK with VC++ 6.
>>>>
>>>> std::vector<bool> smallsieve;
>>>>
>>>> smallsieve.reserve(smsize+1);
>>>>
>>>> memset(smallsieve.begin(), true, smsize+1);
>>>
>>> Well, the code is broken in several ways:
>>>
>>> 1. An iterator is not a pointer.
>> OK. Maybe it's my habit from VC++6. because it works with it (at least
>> for
>> std::vector<T>::begin()).
>>
>>> 2. reserve() doesn't change the number of elements in a vector, you mean
>>> resize().
>> No it's reserve(). Again it's OK with VC++6. Yeah right, it's bad. I need
>> to change it.
>
> Danger: reserve() allocates enough memory to store the given number of
> elements, so you can add elements without the vector having to reallocate
> memory. This does not change the size and it does not technically create
> those elements or allow you to access them. Try this with VC6:
>
> std::vector<bool> vec;
> vec.reserve(2);
> memset(smallsieve.begin(), true, 2);
> bvec.push_back(false);
> for(int i=0; i!=3; ++i)
> std::cout << "vec[" << i << "]=" << vec[i] << std::endl;
>
> You could also write a test class that gives you a message whenever it is
> created, copied, assigned and destroyed and put that into a vector. You
> could then actually see the difference between resize() and reserve().
>
> Accessing them is what is called "undefined behaviour", which is
> standardese
> for "you should have checked that yourself and all guarantees are off".
> You
> are accessing these nonexistent elements using memset(). Since you are
> probably never actually changing the size afterwards and the vector on its
> own doesn't touch that memory, you never even notice.
OK.
>
> BTW: I mentioned that you can actually use memset():
>
> std::vector<T> vec;
> vec.resize(n);
> std::memset(&vec.front(), 0, vec.size()*sizeof(T));

This is almost what I did after the suggestions. But without memset because
you can also specify the value to set to resize(), so:

std::vector<bool> vec;
vec.resize(n, true);

>
> This requires that 'T' is a POD, i.e. a type without any constructor,
> virtual function etc. Builtin types, enumerations, unions and C-compatible
> structures are such PODs.
>
> Uli
>
> --
> C++ FAQ: http://parashift.com/c++-faq-lite
>
> Sator Laser GmbH
> Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932