On Tue, Feb 02, 2021 at 12:25:40AM -0500, Laine Stump wrote:
On 2/1/21 5:23 AM, Daniel P. Berrangé wrote:
> On Mon, Feb 01, 2021 at 11:20:04AM +0100, Peter Krempa wrote:
> > On Mon, Feb 01, 2021 at 10:09:25 +0000, Daniel Berrange wrote:
> > > On Mon, Feb 01, 2021 at 11:05:15AM +0100, Peter Krempa wrote:
> > > > On Mon, Feb 01, 2021 at 09:59:57 +0000, Daniel Berrange wrote:
> > [...]
> >
> > > > In such case I'd strongly prefer if we replace all remaining
usage of
> > > > VIR_FREE (even after this commit) right away to
> > > > g_clear_pointer(&ptr, g_free), whithout stretching the pain
across
> > > > multiple spread-out refactoring steps.
> > > >
> > > > I don't have a problem getting rid of it, I just don't want
it to be
> > > > dragging out forever.
> > > A bulk replacement isn't the right approach, because it will lead to
> > > greater code churn. Much usage of VIR_FREE is better replaced by use
> > > of g_autofree. What remains is better replaced by a simple g_free,
> > > only a relatively small amount needs g_clear_pointer. Bulking replacing
> > > everything with g_clear_pointer just means we'll need to replace it
> > > yet again with the desired final solution.
> > Well, that is extremely unlikely to be done soon there's a bit over 4k
> > VIR_FREE's left in various forgotten and unused parts of libvirt that
> > wasn't touched in a long time.
> >
> > Spending time converting the use of those to g_free and g_autofree
> > manually would be in many cases a waste of time.
> >
> > If we ever want to get rid of VIR_FREE in a timely manner it will IMO be
> > better to just replace it by the identical code, and let the cleanups
> > happen gradually and more localized in the parts people care about
> > actually.
> >
> > > Incrementally converting
> > > our codebase is just fine.
> > I'd agree with that, but approach in this commit is somewhere betwen
> > incremental and massive conversion. It picks the low hanging uses, but
> > leaves the ones which will likely stay there for a very long time.
> I'd say it picks the cases which are clearly correct to convert directly
> to g_free, and leaves the cases which are likely going to need to use
> either g_auto* or g_clear_pointer. IMHO this is the correct way to do
> the conversion.
Speaking of "other cases" - here are three classes of
"non-g_autofreeable"
VIR_FREE() that I see a lot of when looking in the conf directory (which
unsurprisingly has 717 of the 4k+ uses of VIR_FREE(). If anyone has
ideas/opinions on these, I wouldn't mind hearing it:
1) calling VIR_FREE() in a virBlahDispose() function to free subordinate
objectspointed to by the objec being disposed of. Is there any reason to
*not* convert those VIR_FREEs to g_free()? There's nothing that would ever
look at the contents of an object after its vir*Dispose() function has been
called is there?
Yep, a virBlahDispose function should be considered the same as
a virBlahFree function. The only difference is that in the former
case the final g_free(blah) of the struct itself is done for you.
2) calling VIR_FREE() in a virBlahClear() function. Technically
these
functions *do* need to set the pointer to NULL, because well, it says it
right there in the name of the function! However, in several of the
instances I checked, the only caller to the vir*Clear() function was a
vir*Free() function that was cleaning up its subordinate objects prior to
freeing itself. Usually those subordinate objects are contained in the
larger object (rather than pointed to) in the name of efficiency (less calls
to mallo... er I mean g_new0()). Do you think there's any point to, e.g.
turning these "virBlah item" members into ",virBlahPtr item" so they
are
gotten rid of with virBlahFree() instead of virBlahClear()? Or is this one
of the cases where it's definitely proper to use g_clear_pointer()
A simpler option might be to just put a "memset(blah, 0, sizeof(blah))"
at the end of the virBlahClear function so that we splatter the entire
struct at once.
3) g_autofree pointers called "tmp", "str",
"nodes", and probably some
others that are re-used several times in a function, and are VIR_FREEd after
each use. Aside from breaking the rule/guideline that you should never
explicitly free an g_autofree pointer, they by definition won't simply go
away by converting to g_autofree - they've already been converted! I can see
two simple ways of eliminating these: 1) make multiple g_autofree char *'s
in each function, once for each usage (will the compiler be smart enough to
optimize these into a single pointer if the usage doesn't overlap?), or 2)
switch to using g_clear_pointer() (is *that* also frowned upon for pointers
that are already g_autofree?)
I think in general we probably prefer to *not* refuse variables multiple
times. Where we do though, I'd say g_clear_pointer is the semantically
correct approach.
4) I know I said three, but there are also several examples of
VIR_FREE()
being called in a loop on the individual items in an array prior to freeing
the array (see every example of calling virBlkioDeviceArrayClear(), for
example). I don't think anyone has spent any time looking into converting
things to use GArray and GPtrArray, but I suppose that's the best way to get
rid of those...
Yep, but using g_free directly is fine here in the meanwhile.
Regards,
Daniel
--
|:
https://berrange.com -o-
https://www.flickr.com/photos/dberrange :|
|:
https://libvirt.org -o-
https://fstop138.berrange.com :|
|:
https://entangle-photo.org -o-
https://www.instagram.com/dberrange :|