Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion vc71 compiler seems to be very buggy
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Doug Harrison [MVP]  
View profile  
 More options May 29 2005, 2:44 am
Newsgroups: microsoft.public.vc.stl
From: "Doug Harrison [MVP]" <d...@mvps.org>
Date: Sun, 29 May 2005 01:44:50 -0500
Local: Sun, May 29 2005 2:44 am
Subject: Re: vc71 compiler seems to be very buggy
On 28 May 2005 22:11:39 -0700, exlo...@ml1.net wrote:

> Very well. You asked me to shatter your confidence in the vc71
> compiler/runtime right? You'll now get what you asked for.
> I stripped down my sources and obfuscated them just for you.
> The bug you are about to observe it TRULY bizarre and freakish!

> Here is how to reproduce - extract 4 files: a.cpp, b.cpp, c.h and
> build.bat and run build.bat. It will produce crash.exe, run it.

> Bizarre thing #1 if you remove <winsock2.h> from a.cpp, rebuild, then
> crash goes away (please note winsock2.h is not even relevant to the
> needs of the program, I do use it though in my code for tcp/ip comm.).

> Bizarre thing #2 if you restore <winsock2.h> in a.cpp the way it was
> and remove member "double a; " from class hahaha in c.h then crash goes
> away too!

> Also it's important to stress that concurrency is NOT an issue with
> this multithreaded program because the main thread waits for the other
> thread to completely finish and disappear before returning (and running
> the destructors).
> And finally note that _endthreadex does NOT have to be run in the
> subordinate thread because the return statement takes care of that
> implicitly.

> Also, comments about the logic of the program are useless because I've
> stripped it and obfuscated it enough that suggestions about the logic
> are meaningless.

> My computer runs XP, latest service pack.

> ----------- build.bat begins ----------------------
> cl -I. -nologo -MDd -EHsc  -W3 -DWINVER=0x400  -c a.cpp -Foa.obj
> cl -I. -nologo -MDd -EHsc  -W3 -DWINVER=0x400  -c b.cpp -Fob.obj
> cl -MDd -EHsc -nologo -Zi -W3 -Fecrash.exe a.obj b.obj
> ----------- build.bat ends ------------------------

> ----------- a.cpp begins --------------------------
> #include <winsock2.h>
> #include <string>
> #include <map>
> #include <stdio.h>

> #include "c.h"
> extern map<string,dainty> *ptr;

> void funct1(void *arg)
> {
>     try {
>    (*ptr)["xxxx"] = dainty();
>     } catch (...) {
>    printf("funct1: unknown exception\n");
>     }

>     printf("exiting funct1\n");
> }
> ------------a.cpp ends  ---------------------------

> ------------b.cpp begins ---------------------
> #pragma warning(disable:4786)
> #include <io.h>
> #include <windows.h>
> #include <process.h>

> #include <stdio.h>

> #include "c.h"

> map<string,dainty> *ptr;
> extern void funct1(void *arg);

> static unsigned __stdcall wrapper_str(void *arg)
> {
>     funct1(0);
>     return 0;
> }

> int main()
> {
>     try {
>    map<string,dainty> mymap;
>    ptr = &mymap;

>    unsigned thrid;
>    HANDLE h = (HANDLE) _beginthreadex(0, 2*8192, wrapper_str, 0, 0,
> &thrid);
>    WaitForSingleObject(h, INFINITE);
>    CloseHandle(h);
>     } catch (std::string &msg) {
>    printf("exception in main: %s\n", msg.c_str());
>     } catch (...) {
>         printf("main: unknown exception caught\n");
>     }
>     return 0;
> }
> ------------b.cpp ends -----------------------

> ----------- c.h begins -----------------------
> #ifndef _c_h_
> #define _c_h_

> #include <string>
> #include <vector>
> #include <map>
> using namespace std;

> class myobject {
> private:
>     void *opaque;
>     volatile unsigned long *refcnt;

>     void delete_myobject() {
>    if(refcnt) {
>        (*refcnt)--;
>        if(*refcnt == 0) {
>            free(opaque);
>            free((void *) refcnt);
>        }
>    }
>     }

> public:
>     myobject() {
>    opaque = malloc(4);
>    if(!opaque) {
>    out: throw string("myobject constructor failed");
>    }

>    refcnt = (volatile unsigned long *) malloc(sizeof *refcnt);
>    if(refcnt == 0) {
>    delete_myobject();
>    goto out;
>    }

>    *refcnt = 0;
>    (*refcnt)++;
>     }

>     myobject(const myobject &arg) : opaque(arg.opaque),
> refcnt(arg.refcnt) {
>    (*refcnt)++;
>     }

>     ~myobject() { delete_myobject(); }

>     myobject &operator=(myobject const& arg) {
>    if(this == &arg)
>        goto out;

>    if(refcnt != arg.refcnt) {
>        delete_myobject();
>        opaque = arg.opaque;
>        refcnt = arg.refcnt;
>        (*refcnt)++;
>    }

>     out: return *this;
>     }
> };

> class hahaha {
> public:
>     double a;
>     unsigned long b;
>     unsigned char c;
>     unsigned char d;
> };

> class my_data {
> public:
>     myobject x_obj;
> };

> class dainty {
> public:
>     hahaha s_day;
>     vector<my_data> s_intra;
>     myobject s_obj;
> };

> #endif /* _c_h_ */
> ------------c.h ends--------------------------

There's a bug in <winsock2.h> such that it changes the packing from the
default 8 to 4 when WIN32 isn't #defined. You're #including c.h in two
different ways; in a.cpp, it follows <winsock2.h>, while b.cpp doesn't
#include <winsock2.h>. I expect this is causing various classes to have
different layouts in these files. You can see the underlying problem if you
add the following line to the top of c.h and following all its #include
directives:

#pragma pack(show)

Then when I compile using your command line, I get:

C>cl -I. -nologo -MDd -EHsc -W3 -DWINVER=0x400 a.cpp b.cpp
a.cpp
c:\temp\c.h(4) : warning C4810: value of pragma pack(show) == 4
c:\temp\c.h(7) : warning C4810: value of pragma pack(show) == 4
c:\temp\c.h(9) : warning C4810: value of pragma pack(show) == 4
c:\temp\c.h(11) : warning C4810: value of pragma pack(show) == 4
b.cpp
c:\temp\c.h(4) : warning C4810: value of pragma pack(show) == 8
c:\temp\c.h(7) : warning C4810: value of pragma pack(show) == 8
c:\temp\c.h(9) : warning C4810: value of pragma pack(show) == 8
c:\temp\c.h(11) : warning C4810: value of pragma pack(show) == 8

I think that in general, if you're going to use the Windows SDK, you should
#include <windows.h> before any other Windows header, which would avoid
this problem without you having to remember to specify /DWIN32 for these
command lines you create yourself.

--
Doug Harrison
Microsoft MVP - Visual C++


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google