From: aslan on 2 Dec 2009 05:08 "aslan" <aslanski2002(a)yahoo.com>, iletisinde şunu yazdı, news:ew6718ycKHA.5156(a)TK2MSFTNGP04.phx.gbl... > > "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); > My further finding is that resize() is slow if you want to initialize the same memory area more than once if you are using the same number of elements. So in that case it makes sense to use memset for the following initializations: std::vector<bool> bigsieve; bigsieve.resize(sep, true); int offset=-sep; while (offset+=sep, offset<limit) { // blah blah blah memset(&bigsieve.front(), true, sep); // this is faster }Of course this is valid for VC6. >> >> 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: Tim Roberts on 3 Dec 2009 00:42 "aslan" <aslanski2002(a)yahoo.com> wrote: > >bool happens to be 8-bit integer in VC++6 case, so again it's working there. You just aren't paying attention. There is no type smaller than "char" in C or C++, so sizeof(bool) cannot report less than 1. HOWEVER, STL contains a special exception for std::vector<bool>, so that implementations can pack 8 bools into each byte. The MSVC implementation, EVEN IN VC++6, does this. When you do this: std::vector<bool> boo; boo.reserve(32); there are only FOUR bytes of data in the vector. FOUR bytes, not 32 bytes. If you clear 32 bytes, you are overwriting 28 bytes beyond the end of the array. Allocations happen to be done in units of dwords, so even if you only reserve 2 bools, you'll actually have 4 bytes. Maybe that's why you haven't trashed anything important yet. You have all the code (in include\vector). You can go look it up yourself. vector<bool> uses allocator<unsigned int> to allocate memory, but it passes the sizes divided by 32 (using _Nw(x)). -- Tim Roberts, timr(a)probo.com Providenza & Boekelheide, Inc.
From: aslan on 3 Dec 2009 04:10 "Tim Roberts" <timr(a)probo.com>, iletisinde sunu yazdi, news:9pieh5dkk8vt3m75t6b5frho8ukb8j6id4(a)4ax.com... > "aslan" <aslanski2002(a)yahoo.com> wrote: >> >>bool happens to be 8-bit integer in VC++6 case, so again it's working >>there. > > You just aren't paying attention. There is no type smaller than "char" in > C or C++, so sizeof(bool) cannot report less than 1. > > HOWEVER, STL contains a special exception for std::vector<bool>, so that > implementations can pack 8 bools into each byte. The MSVC implementation, > EVEN IN VC++6, does this. I don't use MSVC implementation but the one from Silicon Graphics Computer Systems, Inc. > > When you do this: > std::vector<bool> boo; > boo.reserve(32); > there are only FOUR bytes of data in the vector. FOUR bytes, not 32 > bytes. > If you clear 32 bytes, you are overwriting 28 bytes beyond the end of the > array. > OK I tried something else. struct bool_struct { bool a[32]; }; int main(int argc, char**argv) { bool_struct* p=new bool_struct; return 0; } so "new bool_struct" ends up by calling the following cb=32. void * operator new( unsigned int cb ) { void *res = _nh_malloc( cb, 1 ); return res; } So 32 byte is allocated for "bool a[32];" Also the following quote from MSDN help installed with VC++ 6 which confirms the size of 1 byte for VC++ 6; Microsoft Specific In Visual C++4.2, the Standard C++ header files contained a typedef that equated bool with int. In Visual C++ 5.0 and later, bool is implemented as a built-in type with a size of 1 byte. That means that for Visual C++ 4.2, a call of sizeof(bool) yields 4, while in Visual C++ 5.0 and later, the same call yields 1. This can cause memory corruption problems if you have defined structure members of type bool in Visual C++ 4.2 and are mixing object files (OBJ) and/or DLLs built with the 4.2 and 5.0 or later compilers. END Microsoft Specific > Allocations happen to be done in units of dwords, so even if you only > reserve 2 bools, you'll actually have 4 bytes. Maybe that's why you > haven't trashed anything important yet. > > You have all the code (in include\vector). You can go look it up > yourself. > vector<bool> uses allocator<unsigned int> to allocate memory, but it > passes > the sizes divided by 32 (using _Nw(x)). > -- > Tim Roberts, timr(a)probo.com > Providenza & Boekelheide, Inc.
From: aslan on 3 Dec 2009 04:51 "aslan" <aslanski2002(a)yahoo.com>, iletisinde sunu yazdi, news:e0Vyth$cKHA.5472(a)TK2MSFTNGP02.phx.gbl... > > "Tim Roberts" <timr(a)probo.com>, iletisinde sunu yazdi, > news:9pieh5dkk8vt3m75t6b5frho8ukb8j6id4(a)4ax.com... >> "aslan" <aslanski2002(a)yahoo.com> wrote: >>> >>>bool happens to be 8-bit integer in VC++6 case, so again it's working >>>there. >> >> You just aren't paying attention. There is no type smaller than "char" >> in >> C or C++, so sizeof(bool) cannot report less than 1. >> >> HOWEVER, STL contains a special exception for std::vector<bool>, so that >> implementations can pack 8 bools into each byte. The MSVC >> implementation, >> EVEN IN VC++6, does this. > > I don't use MSVC implementation but the one from Silicon Graphics Computer > Systems, Inc. >> >> When you do this: >> std::vector<bool> boo; >> boo.reserve(32); >> there are only FOUR bytes of data in the vector. FOUR bytes, not 32 >> bytes. >> If you clear 32 bytes, you are overwriting 28 bytes beyond the end of the >> array. >> > OK I tried something else. > > struct bool_struct > { > bool a[32]; > }; > int main(int argc, char**argv) > { > bool_struct* p=new bool_struct; > return 0; > } > > so "new bool_struct" ends up by calling the following cb=32. > > void * operator new( unsigned int cb ) > { > void *res = _nh_malloc( cb, 1 ); > > return res; > } > > So 32 byte is allocated for "bool a[32];" > > > Also the following quote from MSDN help installed with VC++ 6 which > confirms the size of 1 byte for VC++ 6; > > Microsoft Specific > > In Visual C++4.2, the Standard C++ header files contained a typedef that > equated bool with int. In Visual C++ 5.0 and later, bool is implemented as > a built-in type with a size of 1 byte. That means that for Visual C++ 4.2, > a call of sizeof(bool) yields 4, while in Visual C++ 5.0 and later, the > same call yields 1. This can cause memory corruption problems if you have > defined structure members of type bool in Visual C++ 4.2 and are mixing > object files (OBJ) and/or DLLs built with the 4.2 and 5.0 or later > compilers. > > END Microsoft Specific > > > >> Allocations happen to be done in units of dwords, so even if you only >> reserve 2 bools, you'll actually have 4 bytes. Maybe that's why you >> haven't trashed anything important yet. >> >> You have all the code (in include\vector). You can go look it up >> yourself. >> vector<bool> uses allocator<unsigned int> to allocate memory, but it >> passes >> the sizes divided by 32 (using _Nw(x)). >> -- >> Tim Roberts, timr(a)probo.com >> Providenza & Boekelheide, Inc. > I have further tried the following and checked the generated assembly listing: ================================== struct bool_struct { bool a[32]; }; bool_struct bs; void bool_test() { int i=-1; while (++i<32) bs.a[i]=i&1?true:false; printf("size=%d\n", sizeof(bs)); } ================================== PUBLIC ?bool_test@@YAXXZ ; bool_test PUBLIC ??_C@_08ENLC(a)size?$DN?$CFd?6?$AA@ ; `string' ; COMDAT ??_C@_08ENLC(a)size?$DN?$CFd?6?$AA@ ; File D:\aslan\eulerproject\eulerprject.cpp _DATA SEGMENT ??_C@_08ENLC(a)size?$DN?$CFd?6?$AA@ DB 'size=%d', 0aH, 00H ; `string' _DATA ENDS ; COMDAT ?bool_test@@YAXXZ _TEXT SEGMENT ?bool_test@@YAXXZ PROC NEAR ; bool_test, COMDAT ; 1247 : int i=-1; ; 1248 : while (++i<32) xor eax, eax $L11325: ; 1249 : bs.a[i]=i&1?true:false; mov cl, al and cl, 1 mov BYTE PTR ?bs@@3Ubool_struct@@A[eax], cl inc eax cmp eax, 32 ; 00000020H jl SHORT $L11325 ; 1250 : printf("size=%d\n", sizeof(bs)); push 32 ; 00000020H push OFFSET FLAT:??_C@_08ENLC(a)size?$DN?$CFd?6?$AA@ ; `string' call _printf add esp, 8 ; 1251 : } ret 0
From: David Wilkinson on 3 Dec 2009 10:25
aslan wrote: > OK I tried something else. > > struct bool_struct > { > bool a[32]; > }; > int main(int argc, char**argv) > { > bool_struct* p=new bool_struct; > return 0; > } > > so "new bool_struct" ends up by calling the following cb=32. > > void * operator new( unsigned int cb ) > { > void *res = _nh_malloc( cb, 1 ); > > return res; > } > > So 32 byte is allocated for "bool a[32];" > > > Also the following quote from MSDN help installed with VC++ 6 which > confirms the size of 1 byte for VC++ 6; > > Microsoft Specific > > In Visual C++4.2, the Standard C++ header files contained a typedef that > equated bool with int. In Visual C++ 5.0 and later, bool is implemented > as a built-in type with a size of 1 byte. That means that for Visual C++ > 4.2, a call of sizeof(bool) yields 4, while in Visual C++ 5.0 and later, > the same call yields 1. This can cause memory corruption problems if you > have defined structure members of type bool in Visual C++ 4.2 and are > mixing object files (OBJ) and/or DLLs built with the 4.2 and 5.0 or > later compilers. > > END Microsoft Specific All this is about the bool type. In VC6 and beyond, sieof(bool) is 1. The complication is that vector<bool> is not always implemented in the straightforward way that it is for other types. Though it should be, IMHO. -- David Wilkinson Visual C++ MVP |