• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • 💡 We're thrilled to announce that our upcoming texturing contest is in the works, and we're eager to hear your suggestions! Please take this opportunity to share your ideas in this theme discussion thread for the Texturing Contest #34!
  • 🏆 Hive's 7th HD Modeling Contest: Icecrown Creature is now open! The frozen wastes of Icecrown are home to some of Azeroth’s most terrifying and resilient creatures. For this contest, your challenge is to design and model a HD 3D monster that embodies the cold, undead, and sinister essence of Icecrown! 📅 Submissions close on April 13, 2025. Don't miss this opportunity to let your creativity shine! Enter now and show us your frozen masterpiece! 🔗 Click here to enter!

[vJASS] Failing to deallocate

Status
Not open for further replies.

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,226
Hello. I am currently creating a rebirth system. It's supposed to create a unit when a unit dies, and if this new unit is still alive after X seconds the old unit is respawned.

However, my struct fails to deallocate somehow. The message "sss" is displayed but shit keeps updating.


JASS:
struct List
    integer size = 0
    integer array data [99]
    
    public static method create takes nothing returns List
        local thistype this = thistype.allocate()
        return this
    endmethod
    
    public method Add takes integer i returns nothing
        set data[size] = i
        set size = size + 1
    endmethod
    
    public method Remove takes integer id returns nothing
        local integer i = 0
        local integer j = 0
        loop
            exitwhen i >= size
            if data[i] == id then
                loop
                    exitwhen j >= size
                    set data[j] = data[j + 1]
                    set j = j + 1
                endloop
            set size = size - 1
            set i = size + 1 
            endif
            set i = i + 1
        endloop
    endmethod
endstruct


JASS:
globals
	List instances
	integer debugCounter = 0
endglobals

struct Rebirth
	static constant integer DUMMY_TYPE = 'h000'
	static constant real DUMMY_DURATION = 5
	
	integer u
	unit deadUnit
	location l
	real counter
	unit egg
	
	static method onInit takes nothing returns nothing
		set instances = List.create()
	endmethod
	
	static method create takes unit u returns thistype
		local thistype this = thistype.allocate()
		set this.u = GetUnitTypeId(u)
		set this.counter = 0
		set this.deadUnit = u
		set this.l = GetUnitLoc(u)
		set this.egg = CreateUnitAtLoc(GetOwningPlayer(u), DUMMY_TYPE, this.l, 0)
		call instances.Add(this)
		return this
	endmethod
	
	method destroy takes nothing returns nothing
		set this.u = 0
		call RemoveLocation(this.l)
		call instances.Remove(this)
		call this.deallocate()
		call deallocate(this)
		call BJDebugMsg("sss")
	endmethod
	
	method Update takes nothing returns nothing
		set debugCounter = debugCounter + 1
		call BJDebugMsg("Instance: " + I2S(this) + " is being updated!" + "    " + I2S(debugCounter) + "      " + R2S(this.counter))
		set this.counter = this.counter + 0.03
		if this.counter > DUMMY_DURATION then
			call KillUnit(this.egg)
			if IsUnitIdType(this.u, UNIT_TYPE_HERO) == false then
				call CreateUnitAtLoc(Player(0), this.u, this.l, 0)
				call this.destroy()
				call BJDebugMsg("finish1")
			else
				call ReviveHeroLoc(this.deadUnit, this.l, false)
				call this.destroy()
				call BJDebugMsg("finish2")
			endif
		endif
	endmethod
endstruct
  • update
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Custom script: local integer i = instances.size
      • Custom script: loop
      • Custom script: exitwhen i == 0
      • Custom script: call Rebirth( instances.data[i]).Update()
      • Custom script: set i = i - 1
      • Custom script: endloop
 

Attachments

  • rebirth.w3x
    19.8 KB · Views: 69
Level 23
Joined
Apr 16, 2012
Messages
4,041
Whats the call to deallocate(this)?

Are the instances in the list required to be placed in strict order?

You never initialize j in the Remove, so basically it runs from 0 to (size - 1) and basically it only removes the first thing in the list
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,226
1. I don't really understand the question, I added both the deallocate methods to make sure it was removed properly. But it didn't work.

2. Nope.

3. Oh. I added set j = 0 after the inner loop is finished. That's what you mean right?
JASS:
   public method Remove takes integer id returns nothing
        local integer i = 0
        local integer j = 0
        loop
            exitwhen i >= size
            if data[i] == id then
                loop
                    exitwhen j >= size
                    set data[j] = data[j + 1]
                    set j = j + 1
                endloop
            set size = size - 1
			set j = 0
            set i = size + 1 
            endif
            set i = i + 1
        endloop
    endmethod
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
I'm assuming he means initializing j to i's value before starting the second loop since I'm also assuming that the second loop performs a reordering on the list.

Anyway, could you explain what the loops are doing? Thanks.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Try setting j to i before the second loop:

JASS:
   public method Remove takes integer id returns nothing
        local integer i = 0
        local integer j = 0
        loop
            exitwhen i >= size
            if data[i] == id then
            @set j=i@
                loop
                    exitwhen j >= size
                    set data[j] = data[j + 1]
                    set j = j + 1
                endloop
            set size = size - 1
            set j = 0
            set i = size + 1
            endif
            set i = i + 1
        endloop
    endmethod
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,226
Thanks. It seemed to make the bug come less consistantly.. I applied the rebirth to 6 units and 5 of them got revived properly. Before it was like 2-3 out of 6.

This is the current messages being shown:
8dd94e1d339df73a193a024e7299f3a4.png


As you see the timer is at 11 seconds, and it should've been gone after 5 seconds.
Pretty odd, it's always instance 0.
 
Last edited:
Level 22
Joined
Sep 24, 2005
Messages
4,821
the trigger Update was updating the wrong index, remember you store struct pointers in array index size-1?

JASS:
    public method Add takes integer i returns nothing
        set data[size] = i // <-see
        set size = size + 1 // data[size]'s data is invalid at this point.
    endmethod

a quick fix would be:
  • update
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Custom script: local integer i = instances.size
      • Custom script: loop
      • Custom script: exitwhen i == 0
      • Custom script: set i = i - 1
      • Custom script: call Rebirth( instances.data[i]).Update()
      • Custom script: endloop
 
Status
Not open for further replies.
Top