Discussion:
Type cast problem with VC++ 2005 Express Edition
(too old to reply)
aslan
2009-12-01 17:32:28 UTC
Permalink
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).
--
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
Igor Tandetnik
2009-12-01 16:49:05 UTC
Permalink
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
In VC6, vector<T>::iterator happens to be defined as simply T*. Your program improperly relies on this implementation detail.

Further, I'm not sure your code actually ever worked - it might just appear to. You see, vector<bool> is a specialization of the general vector<T> template which packs its values into individual bits. It does not internally contain an array of bool. Chances are, your memset writes over some random memory, and it's only by accident that your program doesn't eventually crash.

Also, vector::reserve doesn't change the size of the vector (size() still returns 0), only its capacity. In light of this, I don't understand the point of this code at all.

If you want to construct a vector with a given number of elements all initialized to the same value, just make it

std::vector<bool> smallsieve(smsize+1, true);
// or
std::vector<bool> smallsieve;
smallsieve.assign(smsize+1, true);
// or
std::vector<bool> smallsieve;
smallsieve.insert(smallsieve.end(), smsize+1, true);
--
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
aslan
2009-12-01 17:08:11 UTC
Permalink
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
In VC6, vector<T>::iterator happens to be defined as simply T*. Your program
improperly relies on this implementation detail.

Further, I'm not sure your code actually ever worked - it might just appear
to. You see, vector<bool> is a specialization of the general vector<T>
template which packs its values into individual bits. It does not internally
contain an array of bool. Chances are, your memset writes over some random
memory, and it's only by accident that your program doesn't eventually
crash.

Also, vector::reserve doesn't change the size of the vector (size() still
returns 0), only its capacity. In light of this, I don't understand the
point of this code at all.

If you want to construct a vector with a given number of elements all
initialized to the same value, just make it

std::vector<bool> smallsieve(smsize+1, true);
// or
std::vector<bool> smallsieve;
smallsieve.assign(smsize+1, true);
// or
std::vector<bool> smallsieve;
smallsieve.insert(smallsieve.end(), smsize+1, true);
--
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

---

Thanks a lot.

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. Anyway I need to
rewrite some pieces as you pointed out.

Aslan
Igor Tandetnik
2009-12-01 17:16:45 UTC
Permalink
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
Alexander Grigoriev
2009-12-02 04:57:48 UTC
Permalink
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.
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
aslan
2009-12-02 07:53:26 UTC
Permalink
Post by Alexander Grigoriev
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
Post by Alexander Grigoriev
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
Ulrich Eckhardt
2009-12-01 16:56:55 UTC
Permalink
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.
2. reserve() doesn't change the number of elements in a vector, you mean
resize().
3. memset() is the wrong tool for this anyway.

Try this

std::vector<bool> smallsieve(smsize+1, true);

to get a vector with 'smsize+1' elements that are all 'true'.

BTW: The C++ standard explicitly allows compressing each element of a
vector<bool> into a single bit, which makes the portable use of memset()
impossible. With all others, you could use memset(), however ugly and
unnecessary that is.

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

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
aslan
2009-12-01 17:23:45 UTC
Permalink
Post by Ulrich Eckhardt
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
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()).
Post by Ulrich Eckhardt
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.
Post by Ulrich Eckhardt
3. memset() is the wrong tool for this anyway.
bool happens to be 8-bit integer in VC++6 case, so again it's working there.
If it's a bitmap in VC++ 2005 EE, you're right.
Post by Ulrich Eckhardt
Try this
std::vector<bool> smallsieve(smsize+1, true);
I did.
Post by Ulrich Eckhardt
to get a vector with 'smsize+1' elements that are all 'true'.
BTW: The C++ standard explicitly allows compressing each element of a
vector<bool> into a single bit, which makes the portable use of memset()
impossible. With all others, you could use memset(), however ugly and
unnecessary that is.
OK
Post by Ulrich Eckhardt
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Thanks a lot.
Ulrich Eckhardt
2009-12-02 07:58:05 UTC
Permalink
Post by aslan
Post by Ulrich Eckhardt
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
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()).
Post by Ulrich Eckhardt
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
aslan
2009-12-02 09:09:49 UTC
Permalink
Post by Ulrich Eckhardt
Post by aslan
Post by Ulrich Eckhardt
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
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()).
Post by Ulrich Eckhardt
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
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.
Post by Ulrich Eckhardt
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);
Post by Ulrich Eckhardt
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
aslan
2009-12-02 10:08:36 UTC
Permalink
Post by aslan
Post by Ulrich Eckhardt
Post by aslan
Post by Ulrich Eckhardt
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
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()).
Post by Ulrich Eckhardt
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
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.
Post by Ulrich Eckhardt
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
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.
Post by aslan
Post by Ulrich Eckhardt
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
Tim Roberts
2009-12-03 05:42:25 UTC
Permalink
Post by aslan
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, ***@probo.com
Providenza & Boekelheide, Inc.
aslan
2009-12-03 09:10:12 UTC
Permalink
Post by Tim Roberts
Post by aslan
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.
Post by Tim Roberts
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
Post by Tim Roberts
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)).
--
Providenza & Boekelheide, Inc.
aslan
2009-12-03 09:51:56 UTC
Permalink
Post by aslan
Post by Tim Roberts
Post by aslan
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.
Post by Tim Roberts
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
Post by Tim Roberts
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)).
--
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 ??***@_08ENLC@size?$DN?$CFd?6?$AA@ ; `string'
; COMDAT ??***@_08ENLC@size?$DN?$CFd?6?$AA@
; File D:\aslan\eulerproject\eulerprject.cpp
_DATA SEGMENT
??***@_08ENLC@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:??***@_08ENLC@size?$DN?$CFd?6?$AA@ ; `string'
call _printf
add esp, 8

; 1251 : }

ret 0
David Wilkinson
2009-12-03 15:25:00 UTC
Permalink
Post by aslan
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
aslan
2009-12-03 15:41:09 UTC
Permalink
Post by David Wilkinson
Post by aslan
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.
OK. Tim Roberts was talking about MS STL implementation whereas I use SGI
STL implementation so I didn't notice it then.
Post by David Wilkinson
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
Tim Roberts
2009-12-06 05:31:19 UTC
Permalink
Post by aslan
OK. Tim Roberts was talking about MS STL implementation whereas I use SGI
STL implementation so I didn't notice it then.
I'm not convinced. The STL implementation in VC++6 was written by PJ
Plauger and contains HP's copyright. HP and SGI cooperated on STL.

Here's a way to tell. Try to compile this:

std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];

If that compiles, then your implementation of STL does not have this
optimization, and the vector probably occupies 32 bytes. If that gets a
compile-time error, then your STL has the same optimization as Microsoft's,
and the vector occupies 4 bytes.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
aslan
2009-12-07 09:41:47 UTC
Permalink
Post by Tim Roberts
Post by aslan
OK. Tim Roberts was talking about MS STL implementation whereas I use SGI
STL implementation so I didn't notice it then.
I'm not convinced. The STL implementation in VC++6 was written by PJ
Plauger and contains HP's copyright. HP and SGI cooperated on STL.
I guess SGI's is based on HP's but with additions and modifications by SGI.

Copyright © 1996-1999
Silicon Graphics Computer Systems, Inc.

Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appears in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation. Silicon Graphics makes no representations about the
suitability of this software for any purpose. It is provided "as is" without
express or implied warranty.

Copyright © 1994
Hewlett-Packard Company

Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appears in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation. Hewlett-Packard Company makes no representations about the
suitability of this software for any purpose. It is provided "as is" without
express or implied warranty.
Post by Tim Roberts
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
If that compiles, then your implementation of STL does not have this
optimization, and the vector probably occupies 32 bytes. If that gets a
compile-time error, then your STL has the same optimization as
Microsoft's,
and the vector occupies 4 bytes.
--
Providenza & Boekelheide, Inc.
aslan
2009-12-07 10:29:39 UTC
Permalink
Post by Tim Roberts
Post by aslan
OK. Tim Roberts was talking about MS STL implementation whereas I use SGI
STL implementation so I didn't notice it then.
I'm not convinced. The STL implementation in VC++6 was written by PJ
Plauger and contains HP's copyright. HP and SGI cooperated on STL.
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
If that compiles, then your implementation of STL does not have this
optimization, and the vector probably occupies 32 bytes. If that gets a
compile-time error, then your STL has the same optimization as
Microsoft's,
and the vector occupies 4 bytes.
--
Providenza & Boekelheide, Inc.
I have found the following in the SGI's documentation. See the warning:



bit_vector

Category: containers Component type: type

Description
A bit_vector is essentially a vector<bool>: it is a Sequence that has the
same interface as vector. The main difference is that bit_vector is
optimized for space efficiency. A vector always requires at least one byte
per element, but a bit_vector only requires one bit per element.
Warning: The name bit_vector will be removed in a future release of the STL.
The only reason that bit_vector is a separate class, instead of a template
specialization of vector<bool>, is that this would require partial
specialization of templates. On compilers that support partial
specialization, bit_vector is a specialization of vector<bool>. The name
bit_vector is a typedef. This typedef is not defined in the C++ standard,
and is retained only for backward compatibility.

Example
bit_vector V(5);
V[0] = true;
V[1] = false;
V[2] = false;
V[3] = true;
V[4] = false;

for (bit_vector::iterator i = V.begin(); i < V.end(); ++i)
cout << (*i ? '1' : '0');
cout << endl;
Definition
Defined in the standard header vector, and in the nonstandard
backward-compatibility header bvector.h.
Ulrich Eckhardt
2009-12-07 12:42:08 UTC
Permalink
Post by Tim Roberts
Post by aslan
OK. Tim Roberts was talking about MS STL implementation whereas I use SGI
STL implementation so I didn't notice it then.
I'm not convinced. The STL implementation in VC++6 was written by PJ
Plauger and contains HP's copyright. HP and SGI cooperated on STL.
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
If that compiles, then your implementation of STL does not have this
optimization, and the vector probably occupies 32 bytes. If that gets a
compile-time error, then your STL has the same optimization as
Microsoft's, and the vector occupies 4 bytes.
Just to put that into historic context: The STL doesn't have a
specialisation of vector<bool>. In the STL, vector<bool> behaves just like
any other vector. What it does have is a vector-like container (bit_vector)
that operates on a sequence of bits.

Now, the C++ standard library does require a specialisation for
std::vector<bool> and that it behave (more or less) like STL's bit_vector.
I seem to remember a class being part of the standard that actually stored
bool objects like a vector, i.e. which then behaves like STL's vector<bool>
again, but I'm not sure about that.

In any case, talking about different STLs and meaning different
implementations of the C++ standard library is what only adds to the
confusion. They are not the same and not even interchangeable, e.g. the STL
doesn't include IOStreams, which form a major part of the C++ standard
library.

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

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Tim Roberts
2009-12-06 05:27:11 UTC
Permalink
Post by aslan
OK I tried something else.
struct bool_struct
{
bool a[32];
};
That is ENTIRELY different. Seriously, are you really unable to see that?
That is a standard C++ array. That is NOT an STL vector. ENTIRELY
different.
Post by aslan
So 32 byte is allocated for "bool a[32];"
Absolutely. And 128 bytes is allocated for an "int a[32]". Neither point
is relevent to the discussion.

The POINT we were talking about is this:

std::vector<bool> a;
a.resize(32);

THAT allocates 4 bytes, not 32 bytes.
Post by aslan
Also the following quote from MSDN help installed with VC++ 6 which confirms
the size of 1 byte for VC++ 6;
Yes, but you are conveniently and repeatedly ignoring the most important
point. "std::vector<bool> a" is NOT the same as "bool a[32]". There is an
special optimization allowed for std::vectors of bool, which allows them to
be packed 8 to a byte. That CANNOT be done for "bool a[32]". For example,
this is legal:

std::vector<int> vi;
vi.resize(32);
int * pi = &vi[0];

After this, pi will point to a 128-byte piece of memory, with room for 32
ints. But when you do this:

std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];

you get a compile-time errror, to prevent you from accidentally overwriting
memory. You were trying to the same kind of thing using vb.begin(), but
the iterator for a std::vector<bool> is not just a pointer. It have to
maintain the the byte offset and the bit number of the current spot. It's
NOT just a pointer to bool.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
aslan
2009-12-07 08:05:13 UTC
Permalink
Post by Tim Roberts
Post by aslan
OK I tried something else.
struct bool_struct
{
bool a[32];
};
That is ENTIRELY different. Seriously, are you really unable to see that?
That is a standard C++ array. That is NOT an STL vector. ENTIRELY
different.
Yes, Sir.
Post by Tim Roberts
Post by aslan
So 32 byte is allocated for "bool a[32];"
Absolutely. And 128 bytes is allocated for an "int a[32]". Neither point
is relevent to the discussion.
std::vector<bool> a;
a.resize(32);
THAT allocates 4 bytes, not 32 bytes.
Post by aslan
Also the following quote from MSDN help installed with VC++ 6 which confirms
the size of 1 byte for VC++ 6;
Yes, but you are conveniently and repeatedly ignoring the most important
point. "std::vector<bool> a" is NOT the same as "bool a[32]". There is an
special optimization allowed for std::vectors of bool, which allows them to
be packed 8 to a byte. That CANNOT be done for "bool a[32]". For example,
std::vector<int> vi;
vi.resize(32);
int * pi = &vi[0];
After this, pi will point to a 128-byte piece of memory, with room for 32
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
No Sir,
I have tried it and I don't get any compile or run-time error with SGI STL
on my machine.

The following is fine for me:

void f()
{
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
pb[31]=true;
}
Post by Tim Roberts
you get a compile-time errror, to prevent you from accidentally overwriting
memory. You were trying to the same kind of thing using vb.begin(), but
the iterator for a std::vector<bool> is not just a pointer. It have to
maintain the the byte offset and the bit number of the current spot. It's
NOT just a pointer to bool.
--
Providenza & Boekelheide, Inc.
Ulrich Eckhardt
2009-12-07 08:43:58 UTC
Permalink
Post by aslan
Post by Tim Roberts
Yes, but you are conveniently and repeatedly ignoring the most important
point. "std::vector<bool> a" is NOT the same as "bool a[32]". There is
an special optimization allowed for std::vectors of bool, which allows
them to be packed 8 to a byte. That CANNOT be done for "bool a[32]".
std::vector<int> vi;
vi.resize(32);
int * pi = &vi[0];
After this, pi will point to a 128-byte piece of memory, with room for 32
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
No Sir,
I have tried it and I don't get any compile or run-time error with SGI STL
on my machine.
The STL is not standard C++. You can install it, but if you then rely on
things where it differs from the C++ standard library, you get exactly what
you got. Let me repeat that: The STL, as far as the C++ standard is
concerned is just a library. Since it also puts symbols into the 'std'
namespace, it could even be called a bad library, as that namespace is
reserved.

Aslan, why are you using the STL anyway? Development of it was abandoned
more than half a decade ago. Most parts of it have been incorporated into
the C++ standard (which is probably the reason many people confuse the
two), so they are available in a standard-conformant way there. I see no
reason to use the STL in modern code.

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

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
aslan
2009-12-07 09:12:21 UTC
Permalink
Post by Ulrich Eckhardt
Post by aslan
Post by Tim Roberts
Yes, but you are conveniently and repeatedly ignoring the most important
point. "std::vector<bool> a" is NOT the same as "bool a[32]". There is
an special optimization allowed for std::vectors of bool, which allows
them to be packed 8 to a byte. That CANNOT be done for "bool a[32]".
std::vector<int> vi;
vi.resize(32);
int * pi = &vi[0];
After this, pi will point to a 128-byte piece of memory, with room for 32
std::vector<bool> vb;
vb.resize(32);
bool * pb = &vb[0];
No Sir,
I have tried it and I don't get any compile or run-time error with SGI STL
on my machine.
The STL is not standard C++. You can install it, but if you then rely on
things where it differs from the C++ standard library, you get exactly what
you got. Let me repeat that: The STL, as far as the C++ standard is
concerned is just a library. Since it also puts symbols into the 'std'
namespace, it could even be called a bad library, as that namespace is
reserved.
Aslan, why are you using the STL anyway? Development of it was abandoned
more than half a decade ago. Most parts of it have been incorporated into
the C++ standard (which is probably the reason many people confuse the
two), so they are available in a standard-conformant way there. I see no
reason to use the STL in modern code.
Uli
6 or 7 years ago, I was developing some code using STL and VC++ 6 (I still
use it mostly due to my job requirements)
and I had some problems with MS STL and decided to give a try to SGI STL and
was satisfied with it. So I still use it.

For my pesonal projects also I still use VC++ 6 and STL combo.

It was recently that I tried to compile a program using VC++ 2005 EE to see
if I could get any speed improvement. Well I could port it VC++ 2005 EE
using the suggestions I received in this thread but there was no speed
improvement even it was slightly slower.
Post by Ulrich Eckhardt
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
David Wilkinson
2009-12-01 17:17:55 UTC
Permalink
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
However I get the following error for the memset line.
1>c:\users\aslan\documents\visual studio
2005\projects\projecteuler\projecteuler\projecteuler.cpp(63) : error
C2664: 'memset' : cannot convert parameter 1 from
'std::_Vb_iterator<_MycontTy>' to 'void *'
1> with
1> [
1> _MycontTy=std::vector<bool,std::allocator<bool>>
1> ]
1> No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called
How can I fix it?
Aslan:

There are a lot of things wrong here:

1. Your code assumes that vector iterators are pointers, which they are in VC6,
but not in later versions.

2. You are using reserve() when you should be using resize()

3. You are assuming that bool is the same size as char (and that vector<bool> is
implemented in a straightforward way -- see below).

Do like this

int smsize = 10;
std::vector<bool> smallsieve(smsize+1, true);

There is also the issue that there is (in some compilers) something special
about the way vector<bool> is implemented. See

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98

Because vector<bool> seems so messed up I always use vector<int>.
--
David Wilkinson
Visual C++ MVP
aslan
2009-12-01 17:43:12 UTC
Permalink
Post by David Wilkinson
The following code compiles (and runs) OK with VC++ 6.
std::vector<bool> smallsieve;
smallsieve.reserve(smsize+1);
memset(smallsieve.begin(), true, smsize+1);
However I get the following error for the memset line.
1>c:\users\aslan\documents\visual studio
2005\projects\projecteuler\projecteuler\projecteuler.cpp(63) : error
C2664: 'memset' : cannot convert parameter 1 from
'std::_Vb_iterator<_MycontTy>' to 'void *'
1> with
1> [
1> _MycontTy=std::vector<bool,std::allocator<bool>>
1> ]
1> No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called
How can I fix it?
1. Your code assumes that vector iterators are pointers, which they are in
VC6, but not in later versions.
OK.
Post by David Wilkinson
2. You are using reserve() when you should be using resize()
I prefer reserve() in this case because it allocates a big chunk of memory
at once. Then you can call resize() (many times) of course but without any
reallocation taking place unless resize is called with a bigger size than
the reserve() has been called. Or again am I wrong here? I describe what
happens with VC++6.
Post by David Wilkinson
3. You are assuming that bool is the same size as char (and that
vector<bool> is implemented in a straightforward way -- see below).
Do like this
int smsize = 10;
std::vector<bool> smallsieve(smsize+1, true);
There is also the issue that there is (in some compilers) something
special about the way vector<bool> is implemented. See
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98
Because vector<bool> seems so messed up I always use vector<int>.
Thanks. I didn't bother with that because I mostly work with VC++6 and it's
working fine there.
Post by David Wilkinson
--
David Wilkinson
Visual C++ MVP
Many thanks.

Aslan
Igor Tandetnik
2009-12-01 18:13:33 UTC
Permalink
Post by aslan
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.
--
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
aslan
2009-12-02 07:49:03 UTC
Permalink
Post by aslan
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
Continue reading on narkive:
Search results for 'Type cast problem with VC++ 2005 Express Edition' (Questions and Answers)
8
replies
whats bether ps3 or xbox 360?
started 2008-01-18 18:29:54 UTC
video & online games
Loading...