nsCOMPtr.h: ~nsCOMPtr_base problems

VERIFIED INVALID

Status

()

Core
XPCOM
P3
normal
VERIFIED INVALID
18 years ago
9 years ago

People

(Reporter: edburns, Assigned: Scott Collins)

Tracking

Trunk
x86
Windows NT
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: STANLEY WORKAROUND)

(Reporter)

Description

18 years ago
Hi,

When compiling webclient *WITHOUT* MOZ_DEBUG=1, I get an undefined symbol when 
trying create my DLL with link.  

WindowControlImpl.obj : error LNK2001: unresolved external symbol "public: 
__thiscall nsCOMPtr_base::~nsCOMPtr_base(void)" (??1nsCOMPtr_base@@QAE@XZ)

However, When I comment out this line from nsCOMPtr.h:

#define NSCAP_FEATURE_FACTOR_DESTRUCTOR

And recompile and link, I do not get the unresolved symbol.

When I try the same thing, *WITH* MOZ_DEBUG=1, I do not get this error.

I'm sure this has to do with this macro in nsCOMPtr.h:

#ifdef NS_DEBUG
  #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
  #define NSCAP_FEATURE_DEBUG_PTR_TYPES
#endif

Can someone please fix this.

Thanks,

Ed

Comment 1

18 years ago
Over to the god of COMPtr, scc.
Assignee: dp → scc
(Assignee)

Comment 2

18 years ago
The problem here is that there is a debug feature of |nsCOMPtr| that was much 
requested.  That feature is controlled by |NSCAP_FEATURE_DEBUG_PTR_TYPES|.  The 
feature is, that in a debug build, an |nsCOMPtr| holds a pointer whose _static_ 
type is the real type of the interface pointed to, e.g., an |nsCOMPtr<
nsISimpleEnumerator>| has a |nsISimpleEnumerator*| in it to allow for easier 
debugging.  When this feature is disabled, as it always is in code compiled with 
debugging off, significant space savings are realized by factoring much of the |
nsCOMPtr| implementation into a non-template base class, |nsCOMPtr_base|.  A 
member of this base class holds the real pointer as an |nsISupports*| (since the 
factored base class can't know the templatized |nsCOMPtr| type).  Debugging is 
harder in this case since you can't `follow the pointer' with your source-level 
debugger.

This is all well and good as long as both "nsCOMPtr.cpp" and all clients of |
nsCOMPtr| are compiled with the same setting of |
NSCAP_FEATURE_TEST_DEBUG_PTR_TYPES|.  But imagine what happens when 
"nsCOMPtr.cpp" is compiled with this facility turned _on_ (e.g., if XPCOM was 
compiled for debugging), but some client was compiled with this facility turned 
_off_.  In this case the client expects that an |nsCOMPtr| inherits from |
nsCOMPtr_base| which should exist and provides a destructor (and some other 
functions) that is (are) exported by the XPCOM dll.

But since the dll itself was compiled with |..._DEBUG_PTR_TYPES| turned _on_, |
nsCOMPtr| does not inherit from |nsCOMPtr_base|, and your linker has not seen fit 
to export its methods.  Depending on your use of |nsCOMPtr| some or all of the 
methods of |nsCOMPtr_base| may be needed.  In your case, apparently, only the 
destructor is required.  If your code used |nsCOMPtr|s more heavily, undoubtably 
you would soon require the other methods supplied by |nsCOMPtr_base|.

It happens that there is a switch to help manage implementation size across 
different platforms called |NSCAP_FEATURE_FACTOR_DESTRUCTOR|.  On most platforms, 
it's a space win if the |nsCOMPtr_base| provides the single destructor for |
nsCOMPtr|s.  The unintended side effect of this switch is that un-defining it 
happens to make available the one thing you need ... a destructor.  But the fact 
that commenting this out allows you to compile is not a fix.  |nsCOMPtr| clients 
and the implementation in the XPCOM dll still disagree about some pretty basic 
things.  It may compile, but it is fragile, and wrong.

The unfortunate compromise we accepted in providing this debugging feature is 
that this flag must have the same setting in every dll.  When people hit this 
error it usually means that some new library is not respecting the setting of |
NS_DEBUG|, which by default, controls |NSCAP_FEATURE_DEBUG_PTR_TYPES|.  Your best 
bet is to find the errant library and make sure it appropriately sets |NS_DEBUG| 
and/or |MOZ_DEBUG|.  If you actually want to mix debug and non-debug components, 
you must disable this |nsCOMPtr| debugging facility across the board with |
NSCAP_DISABLE_DEBUG_PTR_TYPES|.

This problem and its implications are discussed in the |nsCOMPtr| user manual at

  <http://www.mozilla.org/projects/xpcom/nsCOMPtr.html>

in the section labeled "Implementation Details and Debugging Machinery".

<pavlov@netscape.com> says he gave you the simple version of this answer already.  
I hope this more detailed explanation makes it clear.  The entire app must be 
built with the same setting of |NSCAP_FEATURE_DEBUG_PTR_TYPES|.  Unless you do 
special work to control this facility distinctly from other debug facilities 
(which you _can_ do), you will have to build the entire app debug, or else build 
the entire app non-debug.
Status: NEW → RESOLVED
Last Resolved: 18 years ago
Resolution: --- → INVALID
(Reporter)

Comment 3

18 years ago
Added Stanley to status.
Whiteboard: STANLEY WORKAROUND

Comment 4

18 years ago
Adding verifyme keyword.
Keywords: verifyme
(Reporter)

Comment 5

18 years ago
Why is this invalid?

Comment 6

18 years ago
Ed, there is a Tolstoy novel up there! Read the bug!

Comment 7

18 years ago
yes...read the novel.  Looks like Verified/Invalid to me.  Ed, reopen if you 
disagree.
Status: RESOLVED → VERIFIED

Updated

9 years ago
Keywords: verifyme
You need to log in before you can comment on or make changes to this bug.