javacpp-presets icon indicating copy to clipboard operation
javacpp-presets copied to clipboard

Point2f value changing

Open Wouter1 opened this issue 2 years ago • 4 comments

Run tihs program

package test;

import java.util.LinkedList;
import java.util.List;

import org.bytedeco.opencv.opencv_core.Point2f;
import org.bytedeco.opencv.opencv_core.RotatedRect;
import org.bytedeco.opencv.opencv_core.Size2f;

public class Test {
	private final Point2f center;

	public Test(RotatedRect rotatedRect) {
		this.center = rotatedRect.center();
	}

	public Point2f getCenter() {
		return center;

	}

	public static void main(String[] args) {
		List<Test> list = new LinkedList<Test>();
		for (int x = 0; x < 10; x++) {
			Test t = new Test(
					new RotatedRect(new Point2f(x, x), new Size2f(1f, 2f), 44));
			list.add(t);
		}
		System.gc();
		System.out.println(list.get(4).getCenter().x());
	}
}

Observed behaviour: The output is something like -5.475288E-24

Disable the line with System.gc() Now the output is 4.0

Expected behaviour: The behaviour of the program should be completely independent of how many times you call gc().

I think the issue is the same as https://github.com/bytedeco/javacpp-presets/issues/644 #644

Wouter1 avatar Jan 12 '23 13:01 Wouter1

What I think is happening is

  • you free the RotatedRect when it goes out of scope (which is the main loop)
  • The gc() call then frees the memory
  • The Point2f is "hard coded" into the RotatedRect on the C side and also is freed at that moment

So this is not so easy to resolve. I see a few possibilities

  1. return a COPY of the Point2f when I call rotatedRect.center(). Of course you can NOT modify the RotatedRect object then by doing rotatedRect.center().setValue(...) as then you would modify only the copy.
  2. Add some GC system on the C side, that detects that someone is holding a pointer to the Point2f and therefore the RotatedRect should not be freed

Maybe there are other options. But as it is it is very confusing for java users, there is no warning, and this can trigger segfaults at any time.

Wouter1 avatar Jan 12 '23 13:01 Wouter1

It's easy enough to resolve using PointerScope: http://bytedeco.org/news/2018/07/17/bytedeco-as-distribution/

If RotatedRect isn't making a copy of Point2f, that's not a problem with JavaCPP. That's just how the C++ API is.

saudet avatar Jan 12 '23 13:01 saudet

If RotatedRect isn't making a copy of Point2f, that's not a problem with JavaCPP.

@saudet I'm not sure what you are meaning there. A perfectly normal java program that either runs inconsistent/nondeterministic or do a segfault? This is not acceptable from a normal java point of view.

I dont see any problem in the java program so then it seems either javaCPP or C that is causing the crash?

Wouter1 avatar Jan 12 '23 13:01 Wouter1

@saudet I'm not sure what you are meaning there. A perfectly normal java program that either runs inconsistent/nondeterministic or do a segfault? This is not acceptable from a normal java point of view.

Yes, well you're not looking at the right level of abstraction then. Someone will need to work on wrappers like that, possibly as part of JavaCV, contributions are welcome: https://github.com/bytedeco/javacv/

I dont see any problem in the java program so then it seems either javaCPP or C that is causing the crash?

The same thing would occur in C++. In cases like that, it makes sense to just create a copy of the Point2f with something like this:

this.center = new Point2f().put(rotatedRect.center());

saudet avatar Jan 13 '23 00:01 saudet