VC8, Adding __event to non-CLR code gives error C2712  
Author Message
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

In a non-CLR class I have a number of __events defined. When compiling the source code in which the corresponding header file has these __events, I receive the error:

error C2712: Cannot use __try in functions that require object unwinding

pointing to the last of the __event lines in my header file.

When I look at the error message it says:

"cannot use __try in functions that require object unwinding".

Further it is mentioned that "object unwinding" means "destruction".

Needless to say I am not using __try anywhere but perhaps the code being generated by the __event extended keyword is. I have no idea what the function that "requires object unwinding" is. How do I resolve this issue This problem did not occur for the same code under VC7.1, and frankly I do not understand why the generated __try keyword can not work with objects which have destructors.


Visual C++13  
 
 
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

I have isolate this case to a header, source, and compiler options.

Here is the header file:

===================================================================================

// RegularExpression.h: interface for the RegularExpression class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_REGULAREXPRESSION_H__D4133B40_BB9D_11D3_BD0C_000000000000__INCLUDED_)
#define AFX_REGULAREXPRESSION_H__D4133B40_BB9D_11D3_BD0C_000000000000__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afx.h>
#include <vector>

#if defined(BUILD_REGULAR_EXPRESSION)
#define REGULAR_EXPRESSION_IMPORT_EXPORT __declspec(dllexport)
#else
#define REGULAR_EXPRESSION_IMPORT_EXPORT __declspec(dllimport)
#endif

#pragma pack(push,8)

struct REMatch { CString string; unsigned position; };
typedef std::vector<REMatch> REMatchInfo;

class REGULAR_EXPRESSION_IMPORT_EXPORT RegularExpression : public CObject
{
public:

/* 1) */ __event void OnSearching(RegularExpression *,const REMatchInfo &,unsigned,unsigned);
/* 2) */ __event void OnChangingFiles(RegularExpression *,CString,const REMatchInfo &,unsigned,bool &);

RegularExpression();
virtual ~RegularExpression();

// Overridables
virtual void Serialize(CArchive &);

#if defined(_DEBUG)
// Diagnostic Support
virtual void AssertValid() const;
virtual void Dump(CDumpContext &) const;
#endif

private:

DECLARE_SERIAL(RegularExpression)
};

#pragma pack(pop)

#endif // !defined(AFX_REGULAREXPRESSION_H__D4133B40_BB9D_11D3_BD0C_000000000000__INCLUDED_)

==================================================================================

Here is the source file:

==================================================================================

// RegularExpression.cpp: implementation of the RegularExpression class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "RegularExpression.h"

IMPLEMENT_SERIAL(RegularExpression, CObject, VERSIONABLE_SCHEMA|2)

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

RegularExpression::RegularExpression()

{

}

RegularExpression::~RegularExpression()
{

}

// Overridables

void RegularExpression::Serialize(CArchive& ar)

{

CObject::Serialize(ar);

}

#if defined(_DEBUG)

// Diagnostic Support

void RegularExpression::AssertValid() const

{

CObject::AssertValid();

}

void RegularExpression::Dump(CDumpContext& dc) const

{

CObject::Dump(dc);

}

#endif

===============================================================================

Here are the compiler options in VC7.1 ( VS2003 .NET )

===============================================================================

/Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_AFXEXT" /D "BUILD_REGULAR_EXPRESSION" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Yu"stdafx.h" /Fp"Debug/RegularExpressionComponentDllVc71d.pch" /Fo"Debug/" /Fd"Debug/vc70.pdb" /W3 /nologo /c /Wp64 /ZI /TP

===============================================================================

Here are the compiler options in VC8 ( VS2005 )

===============================================================================

/Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_AFXEXT" /D "BUILD_REGULAR_EXPRESSION" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Yu"stdafx.h" /Fp"Debug\RegularExpressionComponentDllVc8d.pch" /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /nologo /c /Wp64 /ZI /TP /errorReport:prompt

===============================================================================

In both VC7.1 and VC8 I create an MFC DLL as an MFC extension DLL.

In VC7.1 the source file will compile without error.

In VC8 I get the error C2712: Cannot use __try in functions that require object unwinding. It points to the line marked as /* 2) */ in the header file above. If I eliminate that line, the first __event line, marked as /* 1) */ does not give an error. I suspect it is because CString must be deleted in the generated __try block. However this error does not occur in VC7.1 . If I change the CString parameter to const CString & the error goes away. However I am loath to do this for my events because I will be breaking, even ever so slightly, backward compatibility for my library.

 
 
Brian Kramer





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

It appears that it will take too much work and assumptions on the part of this forum's participants to reproduce your problem. Can you repost a CLR console app that reproduces the problem, using as few lines as needed to demonstrate that problem


 
 
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

I just gave a source file and header file and specified that this is an MFC extension DLL. What more could you possibly want to reproduce this How hard is it to create an MFC extension DLL project and add the source file which I have typed above, make sure the header file above is included, set the appropriate compiler options in the IDE, and compile the source file That should show the error I have specified.

 
 
Brian Kramer





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

I am merely trying to make it more likely that you'll get to the bottom of this. Most people prefer to analyze the problem in the posting first, which makes it a better strategy to isolate the problem small enough that it can be read and/or copied to a simple console project. In addition, when you pose a complex scenario (an MFC Extension DLL along with an associated MFC executable qualifies, IMO), there is the risk of not seeing the problem which further takes up time.

> "How hard is it to create an MFC extension DLL project and add the source file which I have typed above, make sure the header file above is included, set the appropriate compiler options in the IDE, and compile the source file "

It's not a matter of difficulty, it's a matter of certainty.

Have you determined that an MFC Extension DLL is needed to manifest the problem

Bran


 
 
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

"I am merely trying to make it more likely that you'll get to the bottom of this. Most people prefer to analyze the problem in the posting first, which makes it a better strategy to isolate the problem small enough that it can be read and/or copied to a simple console project. In addition, when you pose a complex scenario (an MFC Extension DLL along with an associated MFC executable qualifies, IMO), there is the risk of not seeing the problem which further takes up time."

The actual class is far more complicated than what I posted above. I spent a good bit of time reducing it down to the simplicity above.

"Have you determined that an MFC Extension DLL is needed to manifest the problem "


I have determined that it occurs in an MFC extension DLL since that is what I am developing. I have not tried to determine if it happens in other scenarios. I ran across this in an MFC extension DLL class I am developing which worked without problem in VC7.1 and gave the error mentioned in VC8, using the exact same code. My source and header file works with no problem under VC7.1 but gives the error message specified under VC8. I guess, since you and others find it onerous to reproduce here, I should just report it to MS as a bug and not bother posting bugs on these forums.

Neither you or anybody else has to investigate this and see what may be wrong with VC8 that it gives this error message. But I surely feel that the manner in which I have delineated exactly when it occurs, via the source, header, compiler options, and explanation would allow anyone else to see this bug for himself and set up the IDE to show it.

 
 
Brian Kramer





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

The following code (in any C++ project) also produces the error.  Here, class X substitutes for CString.

class X
{
public:
   ~X()
   {
   }
};

class Foo
{
public:
  
__event void Bar(X);
};

When the Bar() event is called, a temporary object of type X is created.  The error seems to be saying that if an exception occurs within Bar() then X's destructor may not be called.  (Whether or not that's justified, I am not qualified to answer). 

I don't know the details of how the C++ compiler deals with __event, but it is probably wrapping the method with __try block.  It's still possible that there's a bug in how much the compiler is willing to work with this code (I'm assuming there is not and the VC8 compiler is doing a better job of telling you there's a problem).

To remedy your code, you may want to consider not passing CString by value, but by reference.  e.g.

class X
{
public:
   ~X()
   {
   }
};

class Foo
{
public:
  
__event void Bar(const X&);
};

This is so that the instance of X belongs to the method that fires the Bar() event so there is no issue with the destruction of a temporary X.

The MSDN docs for C2712 gives other remedies, none of which seem appealing.

Hopefully a compiler dev will see this thread and comment further.  I do think that the diagostic is obscure since the code contains __event, not __try.

Brian

 

 


 
 
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

I agree totally with your analysis, and assumed the exact same thing as you have found. Nonetheless I do not understand why X's destructor can not be called. This appears to be a changed in the compiler from VC7.1 to VC8. First I do not understand why "__try" is being used in a C++ module rather than the normal "try" for __event s. Secondly I can find nothing that tells me that, when __try is being used and an exception occurs, a temporary object's destructor can not be called. Finally I can find no documentation explaining this change from the VC7.1 compiler to the VC8 compiler, or indeed where the change has been made.

The workaround you suggested I have already implemented for my VC8 __event s. Needless to say this will break compatibility, even if ever so slightly, for my actual class for users handling the events between VC7.1 and VC8. Perhaps I should have originally passed my string by reference anyway rather than by value, but that is more of an afterthought in hindsight based on this change than any hard and fast rule.

I will report this to MS as a bug and I will anticipate that they will tell me it is by design. My report will use your example above since it is cleaner and easier to understand than even my fairly simple example. I will also make a point of telling MS that if their change was intended behavior for __event parameters, it should have at least been documented somewhere.

 
 
Brian Kramer





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

You're right on all your points, and I'm also mystified.

I vaguely seem to recall reading some discussion in my software development past where there was an issue regarding destructors on temporary objects passed as arguments. Maybe this is related to that; maybe the 7.1 compiler implicitly allowed code that it shouldn't have.

Under the default /EHsc flag, __try is used to catch SEH type exceptions, not C++ exceptions. I believe .NET exceptions are implemented on top of SEH. From what I can tell in the __event documentation, this method needs to be compatibile with COM and .NET clients, hence the need for an EH layer.

I'm looking forward to hearing from someone at Microsoft to clarify on why this error occurs. In your bug report, you may want to link this thread so that the tech writers get a better understanding of the fine print that is missing from their existing docs.

Brian


 
 
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

I have submitted this as a bug report at http://http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx feedbackid=458683d2-d9e3-4969-aea6-9e7aaa7163c5 . Thanks for your help.

 
 
Harmomelodic





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

Has there been any action based on your bug report Is there any additional documentation available elucidating what is going on here

I had __try blocks that were broken when I started using VS2005. I disabled /EHsc to get it to work, but I am currently working on a better solution.

Chad Charowhas



 
 
eldiener





PostPosted: Visual C++ Language, VC8, Adding __event to non-CLR code gives error C2712 Top

If you click on the bug submission link you will see what Microsoft had to say about the bug report. Essentially they have postponed documenting the issue until the next release.