Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Zero-size array as struct member

Reply
Thread Tools

Zero-size array as struct member

 
 
Vladimir Jovic
Guest
Posts: n/a
 
      08-20-2010
thomas wrote:
> Passing vectors as arguments out of a dll in windows may crash the
> system when accessing it.


Priceless! And people still pay good money for a crap called windows
 
Reply With Quote
 
 
 
 
Balog Pal
Guest
Posts: n/a
 
      08-20-2010
"Juha Nieminen" <(E-Mail Removed)>

> In which system, exactly?
>
> Unfortunately 'new' (and 'delete') is a rather heavy operation with
> most C/C++ standard memory allocators, and if you use std::vector in
> the place of the struct hack, you will be doing two 'news' instead of
> one malloc().


You keep stating that, but why on earth would vector do two allocations? Or
use anything but placement new at all, that for in compiles to nothing...

> If that's everything you are doing, then there's no practical difference.
> However, if you are instantiating a million objects of the struct type,
> then it starts making a big difference.


Again, where does that difference come from? Please come up with a fair
comparision of the candidates, that do the same thing on the same types, let
the payload struct be POD and your operation a single resize() from the
empty state... Unless certainly you can show different operations the
'hack' can show.

 
Reply With Quote
 
 
 
 
Squeamizh
Guest
Posts: n/a
 
      08-20-2010
On Aug 20, 2:47 am, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> * tni, on 20.08.2010 10:52:
>
> > On 2010-08-20 10:19, thomas wrote:
> >>> In this case the code is ill-formed, since 0-size array declaration is
> >>> illegal in C++ (as well as in C). In other words, arguing about the "out
> >>> of bounds" access here doesn't make much sense, since the code is
> >>> formally non-compilable.

>
> >> Wait.. I don't think it's illegal in C++. At least I will definitely
> >> object making it illegal by the standard community.

>
> > None of the C or C++ standards allow an array size of 0.

>
> > C99 has flexible arrays (which do basically the same thing), but they
> > are not included in C++03. Unfortunately, it doesn't look like C99
> > flexible arrays are part of C++0x either. The somewhat good news is that
> > GCC, Visual C++ 2010 (and presumably Intel C++) do support them.

>
> It's somewhat bad news.
>
> C99 VLAs are, uh, monstrosities.


Agreed, but flexible arrays and VLAs (variable-length arrays) are two
different things. Flexible arrays are just a standardized version of
the struct hack. The OP's struct, using flexible arrays, would look
like this:

struct SvrList {
unsigned int uNum;
GameSvr svr[];
};

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-20-2010
On Aug 20, 9:19 am, thomas <(E-Mail Removed)> wrote:
> On Aug 20, 2:01 am, Andrey Tarasevich <(E-Mail Removed)>
> wrote:
> > Pete Becker wrote:
> > >>>>> Hi, I need your help.
> > >>>>> ----------
> > >>>>> struct SvrList{
> > >>>>> unsigned int uNum;
> > >>>>> GameSvr svr[0]; //line A
> > >>>>> };
> > >>>>> ---------
> > >>>>> Once I declared a struct like this to store server list info.
> > >>>>> It's supposed to be used like this.
> > >>>>> ----------
> > >>>>> SvrList* pList = (SvrList*)malloc(sizeof(
> > >>>>> SvrList) + svrNum*sizeof(GameSvr));
> > >>>>> pList->uNum, pList->svr[0], pList->svr[1].... blabla..
> > >>>> I wouldn't call this fine. Even
> > >>>> pList->svr[0]
> > >>>> is accessing the element that is out of array's bounds, and
> > >>>> that is UB. How come your program is not crashing, or at
> > >>>> least going crazy? Maybe you are just unlucky to have a bug
> > >>>> hidden.
> > >>> It's an old C programmers hack. I've come across this idiom in
> > >>> lot's old C code, particularly driver and os code. Microsoft
> > >>> Win32 is rife with it.
> > >> Except that it's not legal C, either.


> > > Which is why it's referred to above as a "hack". Quite
> > > a common one, too.


> > Usually we use the term "hack" when the code relies on a specific
> > manifestation of undefined (or unspecified) behavior, but otherwise is
> > well-formed.


> > In this case the code is ill-formed, since 0-size array declaration is
> > illegal in C++ (as well as in C). In other words, arguing about the "out
> > of bounds" access here doesn't make much sense, since the code is
> > formally non-compilable.


> Wait.. I don't think it's illegal in C++. At least I will definitely
> object making it illegal by the standard community.


You're about twenty years too late. It was banned by C90.

--
James Kanze
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      08-20-2010
On 20 aug, 17:51, Paavo Helde <(E-Mail Removed)> wrote:
> Öö Tiib <(E-Mail Removed)> wrote in news:73971626-b0d7-4d6e-843f-
> (E-Mail Removed):
>
> > On 20 aug, 14:15, Öö Tiib <(E-Mail Removed)> wrote:

>
> >> Static variables in DLL are allocated in its own memory context.

>
> > No i was wrong here, sorry. I did look into my papers and it was not
> > static variable causing it but several c runtimes were linked
> > statically.

>
> Yes, but it is still easy to get DLL interface working, just pass the
> data pointer always together with the pointer to the deallocation
> function (wrapped into a nice C++ class of course).
>
> One can attempt to do the same with a custom allocator for std::vector,
> but this is much harder to get working as std::vector implementation is
> not under user control and there is no guarantee that std::vectors of
> different implementations (e.g. with _SECURE_SCL macro defined or not)
> are binary compatible (they aren't).


Evil things like that _SECURE_SCL defined or not can screw up
statically linked library as well, so one should always compile
everything in a product with same options.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      08-21-2010
Goran Pusic <(E-Mail Removed)> wrote:
> On Aug 20, 12:34*pm, Juha Nieminen <(E-Mail Removed)> wrote:
>> Öö Tiib <(E-Mail Removed)> wrote:
>> > In C++ you should use vector<int> instead, it is about as fast.

>>
>> * In which system, exactly?
>>
>> * Unfortunately 'new' (and 'delete') is a rather heavy operation with
>> most C/C++ standard memory allocators, and if you use std::vector in
>> the place of the struct hack, you will be doing two 'news' instead of
>> one malloc().

>
> Why? IMO, new and delete are, on the success path, practically
> equivalent on many common implementations. Difference is one if on
> malloc failure, and new is inlined.


You are basing your claims on your personal *opinion*? Rather than,
you know, actually testing it in practice?

> I say this claim of yours is poorly founded.


It's quite well founded. For example, take this short piece of code:

int main()
{
std::set<int> someSet;
for(int i = 0; i < 10000000; ++i) someSet.insert(i);
}

Compiling that with "g++ -O3 -march=native" on my Pentium4 system takes
about 10 seconds. So, where do you think all that time is spent? Perhaps
rearranging the binary tree each time a new element is inserted? That sounds
like something which would take its time.

Nope. The majority of that time is spent *allocating memory*. If I
change the above code to use a very fast memory allocator, such as
http://warp.povusers.org/FSBAllocator/ so that the declaration of 'someSet'
becomes:

std::set<int, std::less<int>, FSBAllocator<int> > someSet;

then the running time drops down to about 2.5 seconds.

From the 10 seconds running time of the original program above over
7.5 seconds is spent solely on memory allocation and deallocation.
That's quite a *lot*. (There are many reasons why this is so, one of the
major ones being that the default allocator is thread-safe, which the
FSBAllocator above isn't.)

'new' and 'delete' are significantly heavy operations.

>> * Additionally, using std::vector there will increase memory fragmentation,
>> making things even worse.

>
> In this case, you can use vector::reserve, so not really.


If you are allocating a million instances of the struct, each such
instance having an std::vector object inside, reserve() would do nothing
to alleviate the memory fragmentation.

> And even locality of reference is not a concern, because allocators
> mostly do a good job of allocating blocks close in space if allocation
> is close in time. E.g.
>
> std::vector* p = new vector;
> p->reserve(X);
>
> is in practice quite OK wrt locality.


Not if the memory is heavily fragmented, which is one major problem here.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      08-21-2010
Öö Tiib <(E-Mail Removed)> wrote:
> Ok points taken. If the "about as fast" is not fast enough and you do
> not need dynamic array then use boost::array<>, it is vector with
> removed overhead of dynamic size. Also it is present in technical
> reports IIRC, so eventually comes to C++ as well.


Exactly how would boost::array make this any faster? There's no
difference. The issue is not reallocation.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      08-21-2010
Balog Pal <(E-Mail Removed)> wrote:
> "Juha Nieminen" <(E-Mail Removed)>
>
>> In which system, exactly?
>>
>> Unfortunately 'new' (and 'delete') is a rather heavy operation with
>> most C/C++ standard memory allocators, and if you use std::vector in
>> the place of the struct hack, you will be doing two 'news' instead of
>> one malloc().

>
> You keep stating that, but why on earth would vector do two allocations? Or
> use anything but placement new at all, that for in compiles to nothing...


How many times does this have to be explained?

If you need to instantiate the struct dynamically, there will be only
one malloc() call if the struct hack is used. However, if the struct hack
is not used, but std::vector or a raw array pointer is used instead, you
will need two allocations: One for the struct and another for the array
inside the struct.

What's so hard to understand in that?

>> If that's everything you are doing, then there's no practical difference.
>> However, if you are instantiating a million objects of the struct type,
>> then it starts making a big difference.

>
> Again, where does that difference come from?


The difference comes from the amount of allocations needed.

If you need to instantiate the struct dynamically one million times,
and the struct hack is used, then one million malloc() calls will suffice.
However, if the struct hack is not used, but std::vector or a raw array
pointer is used instead, you will need two million allocations.

'new' and 'delete' (or malloc() and free()) are quite heavy operations,
so this can have a significant impact in performance. It also increases
memory fragmentation.

> Please come up with a fair
> comparision of the candidates, that do the same thing on the same types, let
> the payload struct be POD and your operation a single resize() from the
> empty state... Unless certainly you can show different operations the
> 'hack' can show.


I don't even understand that paragraph.
 
Reply With Quote
 
Juha Nieminen
Guest
Posts: n/a
 
      08-21-2010
Juha Nieminen <(E-Mail Removed)> wrote:
> Compiling that with "g++ -O3 -march=native" on my Pentium4 system takes
> about 10 seconds.


Of course I meant:

Compiling that with "g++ -O3 -march=native" *and running it* on my
Pentium4 system takes about 10 seconds.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      08-21-2010
On 08/21/10 06:50 PM, Juha Nieminen wrote:
> Goran Pusic<(E-Mail Removed)> wrote:
>> On Aug 20, 12:34 pm, Juha Nieminen<(E-Mail Removed)> wrote:
>>> Öö Tiib<(E-Mail Removed)> wrote:
>>>> In C++ you should use vector<int> instead, it is about as fast.
>>>
>>> In which system, exactly?
>>>
>>> Unfortunately 'new' (and 'delete') is a rather heavy operation with
>>> most C/C++ standard memory allocators, and if you use std::vector in
>>> the place of the struct hack, you will be doing two 'news' instead of
>>> one malloc().

>>
>> Why? IMO, new and delete are, on the success path, practically
>> equivalent on many common implementations. Difference is one if on
>> malloc failure, and new is inlined.

>
> You are basing your claims on your personal *opinion*? Rather than,
> you know, actually testing it in practice?
>
>> I say this claim of yours is poorly founded.

>
> It's quite well founded. For example, take this short piece of code:
>
> int main()
> {
> std::set<int> someSet;
> for(int i = 0; i< 10000000; ++i) someSet.insert(i);
> }


You are cheating. std::set<int> != std::vector<int> and is in no way an
equivalent to a dynamically allocated array.

Try your test with a vector, before and after reserving space (which is
the more realistic comparison).

--
Ian Collins
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
Using an instance of a struct as a member of that struct dutchgoldtony C Programming 15 11-16-2005 11:24 PM
length of an array in a struct in an array of structs in a struct in an array of structs Tuan Bui Perl Misc 14 07-29-2005 02:39 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM
How would I use qsort to sort a struct with a char* member and a long member - I want to sort in order of the long member Angus Comber C Programming 7 02-05-2004 06:41 PM



Advertisments