HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Double Free Troubles

11-08-2007, 08:08 PM#1
MrApples
NewGen is giving me the "Double Free of Group" error a bunch of times( in the GroupNUM function). I thought that I had cleared it up, as I had started a help topic on what the error was, but I guess I didn't.

udg_UnitsOfRelation acts as a carrier for returning, since I can't return groups without leaks.

The messages are only for testing, and the 'store' locals are so that I don't have to create extra globals. It would be appreciated if someone could point out how I am destroying groups twice.
Collapse JASS:

function sub_gor takes nothing returns nothing
    local unit u = GetEnumUnit()
    if ( udg_xi == 1 ) then
        set udg_xr2 = GetUnitStateSwap(UNIT_STATE_MAX_LIFE, u)
    else
        if ( udg_xi == 2 ) then
            set udg_xr2 = GetUnitStateSwap(UNIT_STATE_LIFE, u)
        else
            if ( udg_xi == 3 ) then
                set udg_xr2 = GetUnitStateSwap(UNIT_STATE_MANA, u)
            else
                if ( udg_xi == 4 ) then
                    set udg_xr2 = GetUnitStateSwap(UNIT_STATE_MAX_MANA, u)
                else
                    if ( udg_xi == 5 ) then
                        set udg_xr2 = GetUnitPointValue(u)
                    else
                        set udg_xr2 = GetUnitUserData(u)
                    endif
                endif
            endif
        endif
    endif
    if ( udg_xr2 == udg_xr ) then
        call GroupAddUnit( udg_xg2, u )
                        call DisplayTextToForce( GetPlayersAll(), ( "= " + R2S(udg_xr2)) )
                        call DisplayTextToForce( GetPlayersAll(), ( "num " + I2S(CountUnitsInGroup(udg_xg2)) ) )
    else
        if ((udg_xb == false) and (udg_xr2 < udg_xr)) or ((udg_xb == true) and (udg_xr2 > udg_xr)) then
            call DisplayTextToForce( GetPlayersAll(), ( ">< " + R2S(udg_xr2)) )
            call DestroyGroup(udg_xg2)
            set udg_xg2 = CreateGroup()
            set udg_xr = udg_xr2
            call GroupAddUnit( udg_xg2, u )
        endif
    endif
endfunction


function GetOfRelation_GroupNUM takes group g, integer x, boolean b returns nothing
    local group storeg = null // Set these later(function may have to end early)
    local group storeg2 = null
    local integer storei = 0
    local boolean storeb = false
    local real storer = 0
    local real storer2 = 0
    local unit u = null
    if ( CountUnitsInGroup(g) == 0 ) then     // Is this actually a group?
        call DestroyGroup(g)
        set g = null
        set udg_UnitsOfRelation = CreateGroup()
        return
    endif
    set u = GroupPickRandomUnit(g)     // Need a unit to base it on.
    set storer = udg_xr
    if ( x == 1 ) then // What are we going by?
        set udg_xr = GetUnitStateSwap(UNIT_STATE_MAX_LIFE, u)
    else
        if ( x == 2 ) then
            set udg_xr = GetUnitStateSwap(UNIT_STATE_LIFE, u)
        else
            if ( x == 3 ) then
                set udg_xr = GetUnitStateSwap(UNIT_STATE_MANA, u)
            else
                if ( x == 4 ) then
                    set udg_xr = GetUnitStateSwap(UNIT_STATE_MAX_MANA, u)
                else
                    if ( x == 5 ) then
                        set udg_xr = GetUnitPointValue(u)
                    else
                        if ( x == 6 ) then
                            set udg_xr = GetUnitUserData(u)
                        else
                            set udg_xr = storer
                            call DestroyGroup(g)
                            set g = null
                            set udg_UnitsOfRelation = CreateGroup()
                            return
                        endif
                    endif
                endif
            endif
        endif
    endif
    call GroupRemoveUnit( g, u )
    set storeb = udg_xb     // Store temp globals in function (so we don't change them)
    set storei = udg_xi
    set storer2 = udg_xr2
    set storeg = udg_xg
    set storeg2 = udg_xg2
    call DestroyGroup(udg_xg)
    call DestroyGroup(udg_xg2)
    set udg_xb = b
    set udg_xi = x
    set udg_xg = g
    set udg_xg2 = CreateGroup()
    call GroupAddUnit( udg_xg2, u )
    call ForGroupBJ( g, function sub_gor )
    call DestroyGroup(g)
    set g = null
    set udg_UnitsOfRelation = udg_xg2
    set udg_xb = storeb
    set udg_xi = storei
    set udg_xr = storer
    set udg_xr2 = storer2
    set udg_xg = storeg
    set udg_xg2 = storeg2
    call DestroyGroup(storeg)
    set storeg = null
    call DestroyGroup(storeg2)
    set storeg2 = null
    return
endfunction
11-08-2007, 08:24 PM#2
HINDYhat
Double free's are when you destroy something twice (I think), so you're destroying your group variables more than once in the functions.

Some tips: Clean up your code.
Instead of putting tons of "if" statements, learn to use "elseif"
Collapse JASS:
if SomeCondition then
    call DoNothing()
else
    if SomeOtherCondition then
        call DoNothingEx()
    endif
endif
Can be replaced with
Collapse JASS:
if SomeCondition then
    call DoNothing()
elseif SomeOtherCondition then
    call DoNothingEx()
endif

You also don't need to "return" at the end of a function.
Also try to clean up your nulling/destroying of local handles, because it's really messy and hard to understand the way it is now -.-
11-08-2007, 08:58 PM#3
MrApples
Thanks for stating my problem again.

I'll start using elseif, wasn't aware that was in JASS. Not seeing how the destroying/nulling is messy, variables are destroyed as soon as I'm done with them.

Thanks for your concern.
11-08-2007, 09:00 PM#4
HINDYhat
I meant at the end of your function. There are loads of sets and stuff, and the destroying/nulling is all over the place.

Use comments or spaces to note the locals init, the body of the function, and the nulling/destroying. It's always easier to find bugs that way.
11-08-2007, 10:25 PM#5
MrApples
It's not really a bug I am looking for, i've been lead to believe it's something wrong with my theory. I'm doing something wrong which I thought is right.