From: aslan on

"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
"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

"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

"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
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