codenameone / CodenameOne

Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.
https://www.codenameone.com/
Other
1.72k stars 408 forks source link

IOS miscompilation, results in nullPointerException #3108

Open ddyer0 opened 4 years ago

ddyer0 commented 4 years ago

The attached program does some simple arithmetic (with no pointers) and encounters a nullPointerException on IOS only. The key point that induces the error seems to be the chained assignment found in the function init()


package com.boardspace.dtest;

// 
// demonstrates broken clipping region on the simulator
// issue 3106
//
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Label;
import com.codename1.ui.Stroke;
import com.codename1.ui.geom.GeneralPath;
import com.codename1.ui.geom.Rectangle;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.ui.Graphics;
import com.codename1.ui.Image;
import com.codename1.ui.layouts.BorderLayout;

public class Dtest {

private Form current;
@SuppressWarnings("unused")
private Resources theme;

public void init(Object context) {
    theme = UIManager.initFirstTheme("/theme");
    // Pro only feature, uncomment if you have a pro subscription
    // Log.bindCrashProtection(true);
}
private int initialBoardScaleIndex = 3;
private double boardScaleIndex = initialBoardScaleIndex;
private double newBoardScaleIndex = boardScaleIndex;
private double boardScales[] = {1.0,2.0,3.0,4.0};
private int numBoardScales = boardScales.length;
public double SCALE = 1.5;
public void init()
{

    double isi = boardScaleIndex;
    double tableScale = SCALE;
    isi*=tableScale;
    boardScaleIndex = newBoardScaleIndex = Math.min(numBoardScales-1,(int)(isi*SCALE));

}
public void start() {
    if(current != null){
        current.show();
    }
    Form hi = new Form("Hi >>0 World");
     current = hi;
    hi.setLayout(new BorderLayout());
    hi.addComponent(BorderLayout.CENTER, new Label("Hi Overlay World 2") {
        @Override
        public void paint(Graphics gc) {
            int w = getWidth();
            int h = getHeight();
            gc.setColor(0x909090);  // gray rectangle
            gc.fillRect(0,0,w,h);
            try {
            init();
            gc.setColor(0);
            gc.drawString("no problem "+boardScaleIndex+" "+newBoardScaleIndex,100,100);
            }
            catch(Throwable err)
            {
                gc.setColor(0);
                gc.drawString("error "+err,100,100);
            }
        }

    });
    hi.show();
    Runnable rr = new Runnable (){ 
        public void run() {
            System.out.println("running");
        while(true) 
        { 
          hi.repaint();
          try {
              Thread.sleep(10); 
              }

          catch (InterruptedException e) {};
        }}};
    new Thread(rr).start();
}
public void stop() {
    current = Display.getInstance().getCurrent();
}

public void destroy() {
}
}
shannah commented 4 years ago

Can you share the NPE stacktrace?

ddyer0 commented 4 years ago

Not easily - the standard environment has a printStackTrace but not a getStackTrace which I could use to show the trace in the error message. I have a stack trace from my actual app, but it's not partiularly informative, it ends at the method that contains the code of interest.

ddyer0 commented 4 years ago

7525E2DB-2D6C-4EBA-AFA7-59678E70DC94 Stack trace from the actual app

shannah commented 4 years ago

What is line 625 of commonGameViewer?

ddyer0 commented 4 years ago

At 09:57 AM 5/19/2020, Steve Hannah wrote:

What is line 625 of commonGameViewer?

those are not line numbers, they're some gibberish whose interpretation is known only to xcode.

I found the x = y = Math.min as the culprit line by binary search.

shannah commented 4 years ago

those are not line numbers

Those should be line numbers.

ddyer0 commented 4 years ago

they're not. The might be line numbers in the xcode source. The key line in the actual app is 887, and it contains this newBoardScaleIndex = boardScaleIndex = Math.min(NumBoardScaleIndices-1,(int)(isi*SCALE));

ddyer0 commented 4 years ago

maybe you have a stack trace tool that knows how to unwind the xcode numbers?

shannah commented 4 years ago

Oh. Sorry... I mistook that stack trace for the one that codename one generates on iOS.

ddyer0 commented 4 years ago

Yea, that's one of my pet peeves about codename1 - you classified stack traces as a premium feature, where IMO they are actually essential debugging tools.

shannah commented 4 years ago

If you catch the exception and print it with Log.e(ex), it will print out the stack with java line numbers.

ddyer0 commented 4 years ago

That's exactly what I do, but I don't get the good line numbers. Some other calestentics are necessary to get it to a string instead of printed to stderr. ''''java public static String getStackTrace(Throwable t) { int level = LogCapture.getLevel(); LogCapture cap = new LogCapture(); LogCapture.setLevel(99); Log.e(t); LogCapture.setLevel(level); return cap.dispose();
} ''''