Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

How to debug code that crashes the app?

edited June 2017 in Bugs Posts: 15

I have a problem, I have some code that crashes the app but I don't know where it is. Often to debug I will use prints and errors to find the problem but I can't do that if the app crashes, any tips on how to find my bug?

Tagged:

Comments

  • dave1707dave1707 Mod
    Posts: 9,279

    If the app crashes back to iOS and you can't see normal print statements, you can use something like save project data to save some info. After the app crashed you can restart the app and read project data to see what you saved.

  • Posts: 237

    @ellie_ff1493 it would really help if you showed us the code. If you don't want to, then to add on to what @dave1707 said, look at all the code that is outside of functions, and look at the setup function. Those two are most prone to causing crashes

  • dave1707dave1707 Mod
    Posts: 9,279

    Actually, the thing that causes a Codea program to crash the most is using too much memory before it can be cleared. Just for kicks, add the statement collectgarbage() at the beginning of the draw() function and see if the app still crashes. If it doesn't, then it's a memory issue. Are you drawing/creating a lot of images or using the camera to create images. Those usually cause a crash.

  • Posts: 237

    @dave1707 You are correct, except he is saying that the program isn't even starting up because it crashes immediately. I don't think the program gets a chance to make it to the draw() function

  • dave1707dave1707 Mod
    Posts: 9,279

    @CamelCoder Where does it say that the app crashes on startup. I read that it crashes but they don't know where. They said they would put print statement in the code but they can't because the app crashes. So, does it crash back to iOS. If that's the case, then using saveprojectdata might help because you can go back and see what was saved. As you mentioned, it would help if we could see some code or at least have more information about what's happening.

  • Here is the code

    Bubbles = class()
    
    function Bubbles:init(x, y)
        -- Initialising our bubble emitter
        self.x = x
        self.y = y
        self.bubbles = {}
        self.maxbubbles = 100
        self.bubblecount = 0
        m = mesh()
        m.shader = shader("Project:Stck")
        m:addRect(WIDTH/2, HEIGHT/2, WIDTH-50, HEIGHT-50)
    
        self.m = m
    end
    
    function Bubbles:emit()
        -- Make sure we don't emit more than maxbubbles
        if self.bubblecount < self.maxbubbles then
            local dir = vec2(0,1):rotate(math.random() - 0.5) * math.random(1,6)
            local size = math.random(10, 50)
            local life = math.random(30, 60)
            local bubble = {pos = vec2(self.x, self.y), 
                            dir = dir, 
                            size = size, 
                            life = life}
    
            -- Bubbles have the following properties
            --  dir: direction
            --  size: size of the bubble
            --  life: how many frames the bubble lives
            --  pos: the initial position of the bubble 
            --   (all bubbles start at the emitter position)
    
            -- Add the bubble to our table of bubbles
            table.insert(self.bubbles, bubble)
    
            -- Keep track of how many bubbles we have
            self.bubblecount = self.bubblecount + 1
        end
    end
    
    -- This function updates all the bubbles in the system
    function Bubbles:update()
        -- Loop through bubbles
        for k,v in pairs(self.bubbles) do
            -- Add direction of bubble to its
            --  position, to generate new position
            v.pos = v.pos + v.dir
    
            -- Subtract one from its life
            v.life = v.life - 1
    
            -- If this bubble's life is 0
            if v.life == 0 then
                -- Remove it from the table
                self.bubbles[k] = nil
    
                -- Reduce our bubble count
                --  (we can emit more now!)
                self.bubblecount = self.bubblecount - 1
            end
        end
    end
    
    -- This function draws all the bubbles in the system
    function Bubbles:draw()
        -- Store current style
        pushStyle()
    
        -- Set up our bubble style
        ellipseMode(CENTER)
        stroke(255)
        strokeWidth(4)
        fill(153, 197, 210, 100)
    
        -- Loop through bubbles and draw them
        arr = {}
        for i = 0, 99 do
            v = self.bubbles[i]
            if v==nil then 
                table.insert(arr, vec2(0,0))
    
            else
                table.insert(arr, vec2(v.pos.x/WIDTH, v.pos.y/HEIGHT))
            end
    
    
        end
    
        -- print(#arr)
        self.m.shader.points = arr
    
        self.m.shader.len = #self.bubbles
        self.m:draw()
        for k,v in pairs(self.bubbles) do
            -- ellipse(v.pos.x, v.pos.y, v.size)
        end
    
        -- Restore original style
        popStyle()
    end
    
    -- Use this function to perform your initial setup
    function setup()
    
        displayMode(OVERLAY)
    
        -- Create a global bubble emitter
        emitter = Bubbles(0, 0)
    end
    
    -- This function gets called once every frame
    function draw()
        -- This sets a dark background color 
        background(40, 40, 50)
    
        -- This sets the line thickness
        strokeWidth(5)
    
        -- Do your drawing here
        fill(255)
        text("Drag your finger to make bubbles", WIDTH/1.5, HEIGHT - 40)
    
        -- Update and draw bubbles
        emitter:update()
        emitter:draw()
    end
    
    -- This function gets called whenever a touch event occurs
    function touched(touch)
        -- Whenever the screen encounters a touch event we:
        --  update the emitter position
        --  emit a single bubble
        emitter.x = touch.x
        emitter.y = touch.y
        emitter:emit()
    
        -- Touch events happen when your finger moves, begins
        --  touching or ends touching
    end
    

    And the fragment shader

    precision highp float;
    uniform vec2 points[100];
    uniform int len;
    varying lowp vec4 vColor;
    
    //The interpolated texture coordinate for this fragment
    varying highp vec2 vTexCoord;
    
    void main(){
        float num = 0.;
        for (int i=0; i<len; i++){
            num += 0.02 / distance(vTexCoord, points[i])+0.00001;
        }
        if (num > .8) {
            gl_FragColor = vec4(1,1,1,1);
        }
        else{
            gl_FragColor = vec4(0,0,0,1);
            }
    }
    
  • I have also narrowed it down.
    If I stop the code by pressing back it will crash but if I stop the code it's less likely to crash.
    If I resize the console it will crash

  • dave1707dave1707 Mod
    Posts: 9,279

    @ellie_ff1493 Your code ran without crashing, but it didn't do anything. I made some changes so it would work. At least I think this is what it's supposed to do. I took all the comments out just to shorten the repost. I'm not sure how you were doing the shader, but I changed it to the way I use shaders.

    displayMode(FULLSCREEN)
    
    function setup()
        emitter = Bubbles(0, 0)
    end
    
    function draw()
        background(40, 40, 50)
        fill(255)
        text("Drag your finger to make bubbles", WIDTH/2, HEIGHT - 40)
        emitter:update()
        emitter:draw()
    end
    
    function touched(touch)
        emitter.x = touch.x
        emitter.y = touch.y
        emitter:emit()
    end
    
    Bubbles = class()
    
    function Bubbles:init(x, y)
        self.x = x
        self.y = y
        self.bubbles = {}
        self.maxbubbles = 100
        self.bubblecount = 0
        m = mesh()
        m.shader = shader(sh.v,sh.f)
        m:addRect(WIDTH/2, HEIGHT/2, WIDTH-50, HEIGHT-50)
        self.m = m
    end
    
    function Bubbles:emit()
        if self.bubblecount < self.maxbubbles then
            local dir = vec2(0,1):rotate(math.random() - 0.5) * math.random(1,6)
            local size = math.random(10, 50)
            local life = math.random(30, 60)
            local bubble = {pos = vec2(self.x, self.y), 
                            dir = dir, 
                            size = size, 
                            life = life}
            table.insert(self.bubbles, bubble)
            self.bubblecount = #self.bubbles
        end
    end
    
    function Bubbles:update()
        for k,v in pairs(self.bubbles) do
            v.pos = v.pos + v.dir
            v.life = v.life - 1
            if v.life == 0 then
                self.bubbles[k] = nil
                self.bubblecount = self.bubblecount - 1
            end
        end
    end
    
    -- This function draws all the bubbles in the system
    function Bubbles:draw()
        ellipseMode(CENTER)
        stroke(255)
        strokeWidth(4)
        fill(153, 197, 210, 100)
        arr = {}
        for i = 0, 99 do
            v = self.bubbles[i]
            if v==nil then 
                table.insert(arr, vec2(0,0))
            else
                table.insert(arr, vec2(v.pos.x/WIDTH, v.pos.y/HEIGHT))
            end
        end
        self.m.shader.points = arr
        self.m.shader.len = #self.bubbles
        self.m:draw()
        for k,v in pairs(self.bubbles) do
            ellipse(v.pos.x, v.pos.y, v.size)
        end
    end
    
    sh = 
    {   v=[[
        uniform mat4 modelViewProjection;
        attribute vec4 position;    
        void main()
        {   gl_Position = modelViewProjection * position;
        }
        ]], 
    
        f=[[   
        precision highp float;
        uniform vec2 points[100];
        uniform int len;
        varying lowp vec4 vColor;
        varying highp vec2 vTexCoord;        
        void main()
        {   float num = 0.;
            for (int i=0; i<len; i++)
                num += 0.02 / distance(vTexCoord, points[i])+0.00001;
            if (num > .8) 
                gl_FragColor = vec4(1,1,1,1);    
            else
                gl_FragColor = vec4(0,0,0,1);    
        }
        ]]
    }
    
  • It didn't do anything because the shader wasn't running
    Here is the correct code in your format
    It is a bit more stable but still crashes

    displayMode(FULLSCREEN)
    
    function setup()
        emitter = Bubbles(0, 0)
    end
    
    function draw()
        background(40, 40, 50)
        fill(255)
        text("Drag your finger to make bubbles", WIDTH/2, HEIGHT - 40)
        emitter:update()
        emitter:draw()
    end
    
    function touched(touch)
        emitter.x = touch.x
        emitter.y = touch.y
        emitter:emit()
    end
    
    Bubbles = class()
    
    function Bubbles:init(x, y)
        self.x = x
        self.y = y
        self.bubbles = {}
        self.maxbubbles = 100
        self.bubblecount = 0
        m = mesh()
        m.shader = shader(sh.v,sh.f)
        m:addRect(WIDTH/2, HEIGHT/2, WIDTH-50, HEIGHT-50)
        self.m = m
    end
    
    function Bubbles:emit()
        if self.bubblecount < self.maxbubbles then
            local dir = vec2(0,1):rotate(math.random() - 0.5) * math.random(1,6)
            local size = math.random(10, 50)
            local life = 600
            local bubble = {pos = vec2(self.x, self.y), 
                            dir = dir, 
                            size = size, 
                            life = life}
            table.insert(self.bubbles, bubble)
            self.bubblecount = #self.bubbles
        end
    end
    
    function Bubbles:update()
        for k,v in pairs(self.bubbles) do
            v.pos = v.pos + v.dir
            v.life = v.life - 1
            if v.life == 0 then
                self.bubbles[k] = nil
                self.bubblecount = self.bubblecount - 1
            end
        end
    end
    
    -- This function draws all the bubbles in the system
    function Bubbles:draw()
        ellipseMode(CENTER)
        stroke(255)
        strokeWidth(4)
        fill(153, 197, 210, 100)
        arr = {}
        for i = 0, 99 do
            v = self.bubbles[i]
            if v==nil then 
                table.insert(arr, vec2(0,0))
            else
                table.insert(arr, vec2(v.pos.x/WIDTH, v.pos.y/HEIGHT))
            end
        end
        self.m.shader.points = arr
        self.m.shader.len = #self.bubbles
        self.m:draw()
    
    end
    
    sh = 
    {   v=[[
    
    uniform mat4 modelViewProjection;
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texCoord;
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    void main()
    {
        vColor = color;
        vTexCoord = texCoord;
        gl_Position = modelViewProjection * position;
    }
    
    
        ]], 
    
        f=[[   
        precision highp float;
        uniform vec2 points[100];
        uniform int len;
        varying lowp vec4 vColor;
        varying highp vec2 vTexCoord;        
        void main()
        {   float num = 0.;
            for (int i=0; i<len; i++)
                num += 0.02 / distance(vTexCoord, points[i])+0.00001;
            if (num > .8) 
                gl_FragColor = vec4(1,1,1,1);    
            else
                gl_FragColor = vec4(0,0,0,1);    
        }
        ]]
    }
    
  • dave1707dave1707 Mod
    edited June 2017 Posts: 9,279

    @ellie_ff1493 When I get it to run, it has a bubble/blob that acts like what's in a lava lamp. It looks really nice, but still crashes after awhile. I don't know enough about shaders, so I can't say why it crashes. When you work with shaders, be prepared to debug blind because you won't get any information other than a crash if things don't work right. You never said what this program is really supposed to do.

  • I fixed it, turns out 100 is to large of an array size, I changed it to 10 and it's really stable now

  • I looked in to it some more and it's not the large array it just makes the bug worse, the problem is using a uniform variable in a for loop because it try's to unroll the loop but can't because it's an unknown when it compiles. This also makes a bug where different parts of the screen get rendered in different places like in the pic

    IMG_3666.PNG 75.3K
Sign In or Register to comment.