Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / July 2005

Tip: Looking for answers? Try searching our database.

C++ Crashing Template Bug

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
314ccc@gmail.com - 08 Jul 2005 22:28 GMT
I have stumbled upon a very nasty compiler bug.  I have boiled it down
to the following code.  Granted, this code looks nonsensical, trust
that the original source did much more and solves a specific problem
nicely.  The real question here, is why does the compiler compile this
without any problems, yet generates code that crashes.  This code
should do nothing...absolutely nothing.  There are some comments in
this code that identify places where simple changes can be made to
resolve the crash.  I know I can make the crash go away.  My question
is what is it doing that is crashing?

File 1: One.h
#pragma once

class Two; // crash
//#include "Two.h" // no crash

class One
{
public:
    One(){}
    virtual ~One(){}

protected:
    Two* m_pTwo;
};

File2: Two.h
#pragma once

#include "Three.h"

class One;

class Two
{
public:
    Two();
    virtual ~Two();

private:
    Three<One> m_cThree;
};

File2 (source): Two.cpp
#include "Two.h"

Two::Two()
{
}

Two::~Two()
{
}

File 3: Three.h
#pragma once

class One;

template<class T> class Three
{
public:
    Three();
    virtual ~Three();

private:
    void (One::*m_pOneMethod)();
};

template<class T> Three<T>::Three()
: m_pOneMethod(0)
{
}

template<class T> Three<T>::~Three()
{
}

File4 (test location):

#include "One.h" // comment out this line fixes crash!?
#include "Two.h"

void CTestDlg::OnBnClickedButton1()
{
    Two cTest;
}
Carl Daniel [VC++ MVP] - 09 Jul 2005 00:35 GMT
> I have stumbled upon a very nasty compiler bug.  I have boiled it down
> to the following code.  Granted, this code looks nonsensical, trust
[quoted text clipped - 5 lines]
> resolve the crash.  I know I can make the crash go away.  My question
> is what is it doing that is crashing?

VC++ implements a (strictly speaking non-conforming) optimization which uses
4 different representations for pointers to members.  When you declare a
pointer to a member of an incomplete class, the compiler is forced to choose
the most general representation (16 bytes), but when you declare a pointer
to member of a complete class, the compiler will choose the most efficient
representation (in this case, 4 bytes).

As a result, in this code, when you simply forward declare ClassTwo, you end
up with two different representations for pointers to members of ClassTwo,
which ultimately leads to disaster.

You need to compile this code with /vmg, or use #pragma pointers_to_members.
Look them up in MSDN.

-cd
314ccc@gmail.com - 11 Jul 2005 14:30 GMT
Thank you for this response!  Adding this option takes care of the
problem without any of the mystery that was worrying me.

After reading in the help about the pragma, I am unsure of the scope of
it.  If I only want to use it in this instance would I add inside the
class definition?

template<class T> class Three
{
public:
       Three();
       virtual ~Three();

private:
    #pragma pointers_to_members(full_generality)
       void (One::*m_pOneMethod)();

};
Carl Daniel [VC++ MVP] - 11 Jul 2005 15:24 GMT
> Thank you for this response!  Adding this option takes care of the
> problem without any of the mystery that was worrying me.
[quoted text clipped - 14 lines]
>
> };

No, it applies to a class, not a member, so you'd do

#pragma pointers_to_members(full_generality)
class One;

Once given, the #pragma applies to all subsequent class definitions that
aren't already known to use a different representation, or aren't marked
with one of the inheritance keywords.

In your case, the inheritance keywords (which I neglected to mention in my
earlier reply) are probably the way to go:

// One.h

class __single_inheritance Two;

-cd

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.