Closed
Bug 179275
Opened 22 years ago
Closed 13 years ago
should/can we stop functions that return an |AddRef|ed pointer as a function result from leaking in a void context?
Categories
(Core :: XPCOM, enhancement)
Core
XPCOM
Tracking
()
RESOLVED
INCOMPLETE
People
(Reporter: scc, Unassigned)
References
Details
See bug #172030 comment #47 for the detailed description, I will abstract here.
For a function |f()| that returns a pointer result that has already been
|AddRef|ed, can we prevent |f()| from leaking when used in a |void| context?
Additionally, our solution can be restricted to cases where |f()| has been
declared to return |already_AddRefed<T>|, and perhaps further restricted to
debug builds, if necessary. And if we _can_ do this, _should_ we do this? As
per bug #172030, I think it's certainly worth discussing.
My first question, though: is this really a problem that needs fixing? Because
the typical function that returns such a pointer exists soley to return that
pointer, it seems unlikely that it would appear in a |void| context. That is,
for example, one is unlikely to write
CreateAFoo();
instead of
nsCOMPtr<nsIFoo> fp = CreateAFoo();
There are special cases of this, in particular |do_QueryInterface|,
|do_QueryReferent|, |do_CreateInstance|, |do_GetService|, etc., etc.; however,
all these |do_...| routines are specially constructed already to be no-ops in a
void context. Did I go too far in those cases? I don't know ... maybe. In
favor is that those routines really are no-ops in a void context. It's not that
they don't leak, they don't do _anything_. Solutions under consideration for
this bug don't turn the function calls into no-ops, they just stop them from
leaking, or else report the |void| use as an error. Hmmm, maybe making all the
|do...| routines cause syntax errors in a |void| context would have been better.
Worth considering? Separate bug? What's good for the goose should be good for
the gander. If not-leaking, no-op-ing, or causing-a-syntax-error is good for
one category of this machinery, surely a parallel or identical solution is good
for the other.
Reporter | ||
Updated•22 years ago
|
Status: NEW → ASSIGNED
Comment 1•22 years ago
|
||
If all functions that returned already_AddRefed<T> were getters then this would
not be necessary. In those cases the return value is absolutely implicit in the
function name. But there are other cases that have side effects and return a
value, where callers might just care about the side effects. For example,
consider a hypothetical function:
// Kick off load of a document into the current window
already_AddRefed<nsIRequest> loadDocument(nsAString& aURI);
The nsIRequest is a network channel that one can use to monitor the progress of
the document loading. Some callers may want to load the document and then
monitor it:
nsCOMPtr<nsIRequest> request = loadDocument("http://www.google.com");
// Add yourself as an observer of the request
Others may not care about progress--they just want the document to load.
loadDocument("http://www.google.com");
Now they could create a throwaway request, and in the current model that is what
they *should* do. But it would be natural for a programmer to forget about that
return value because the side effects do everything he wants.
Now, perhaps the function can be rewritten to use the COM calling convention,
but once people learn of already_AddRefed<T> they are *going to use it*. It is
a much cleaner way to manipulate COM objects from classes with non-COM interfaces.
After all that, if we just assert in debug builds it won't cause one byte of
bloat for our shipped builds and it *will* provide a valuable service to
programmers when they screw this up.
Comment 2•22 years ago
|
||
If we do bug #172030 comment #47 or something similar we will get assertions for
free on the do_XXX(). If you use do_QueryInterface(foo()) in void context the
already_AddRefed will not get nulled out and thus will assert when it is destructed.
Comment 3•22 years ago
|
||
Regarding the possibility of protecting callers by releasing the value, we can
do that with a similar mechanism, nulling out the pointer on use and releasing
it on destruction if it is still there. That raises some questions though:
(a) does it break the other COMPtr library rules? I think so. It makes
ownership non-explicit. While that is not much of a problem in void context,
and it appears this will only *happen* in void context, it breaks the model.
(b) is it worth the few bits to fix this in all contexts or would an assertion
in debug builds be better to make optimized builds stay optimized?
I prefer the assertion in debug builds but you've got a good handle on your
model so I defer to your judgement.
Reporter | ||
Comment 4•22 years ago
|
||
Do we have some concrete cases of these functions where their result might be in
jeopardy of leaking out through a |void| context? jkeiser: are there any
functions that exist now that you are thinking of? Or, if there are not
getter-only-as-a-side-effect functions returning |already_AddRefed|, then how
about the same, but returning raw |AddRef|ed pointers?
Comment 5•22 years ago
|
||
Not only those that return T*, but those that do the COM T** method and are due
for restructuring since they are not in COM interfaces and do not return
anything other than NS_OK.
I have been studying these, and each of the major side effect functions
*generally* has to return nsresult because the side effect fails. I think
returning nsresult is going to be the case for many such functions. I am pretty
sure that non-nsresult-returning functions of this nature exist (I remember
having seen such things or saying "we can convert this"), but I am willing to
wait until I find them to do anything on this bug.
However, given that it *does* give us added protection, and does *not* add bloat
or peformance problems in optimized builds, I don't think we're talking about
anything onerous here. And it *could* help catch errors early. One of the
major things people get from nsCOMPtr is near-total safety (and early warning
when they do unsafe things), and we should continue that track record.
Updated•18 years ago
|
Assignee: scc → nobody
Status: ASSIGNED → NEW
QA Contact: scc → xpcom
Comment 6•13 years ago
|
||
I don't think there are many of these left, and if there are we should just be using warn-unused-result on them.
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → INCOMPLETE
You need to log in
before you can comment on or make changes to this bug.
Description
•