From: Alexander Grigoriev on 1 Dec 2009 23:57 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 2 Dec 2009 02:49 "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 2 Dec 2009 02:53 "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 2 Dec 2009 02:58 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 2 Dec 2009 04:09
"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 |