Machine Vision_HALCON_Memory Management_HObject object application release analysis in C#


I. Introduction

When using HALCON and C# for development, if you use HDevelop to export the code, you can see the code similar to the following in the exported code file,

    // Local iconic variables 
    HObject ho_Image=null;
	// Initialize local and output iconic variables 
    HOperatorSet.GenEmptyObj(out ho_Image);
    ...
    ho_Image.Dispose();
    HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);

You can know from the user manual that
insert image description here
ho_Image prefixed with ho_ is an image variable (of course, the root cause is that the HObject class is an image class).
Before ho_Image gets the image from the image device, there is another line of code ho_Image.Dispose();. insert image description here
The reason for adding this line of code is as described in the above figure. The image object in the exported C# code is represented by HObject, but from the perspective of GC, HObject is very small. Therefore it may be ignored. But the bottom layer of HObject may be quite a large piece of memory. In order to avoid leaks, it must be explicitly released before use (that is, use Dispose()).

So the question is, why is HObject not recycled from the perspective of GC? Why can such a small HObject be a rather large piece of memory at the bottom? Why use GenEmptyObj() for memory application, can't you use new HObject?

This article intends to analyze these issues from the results of decompilation in VS.


2. Analysis

1 GenEmptyObj()

In fact, partners who have certain development experience and C language foundation should have a feeling that the bottom layer must have done memory application.
Is that so? We follow two steps into the function,

It can be seen that the underlying object is obtained through new HObject(), but the constructor is different, and some additional processing (acquisition of an error code) is performed before new. And after new, load the image from a lower-level proc pointer (this part should be the management mechanism in HALCON). So GenEmptyObj is essentially a new object, but it has made some judgments and management.

2 Dispose()

Next look at Dispose(),

As you can see, its function is to prevent the GC from cleaning up the object. And keep alive (refer to the specified object, from the beginning of the current routine to the point where this method is called, so that it will not be reclaimed by GC).

So Dispose() didn't do memory cleanup at all?
No, there is a key judgment in the first line.
insert image description here
From the previous decompilation of GenEmptyObj, we can see that the default key of the new object at the bottom layer is UNDEF (if you continue to trace, you will find that it means Zero).
insert image description here

Then find the GrabImage function and decompile it.
insert image description here
You can see that there is also a HObject.LoadNew function inside, and the content is consistent with the LoadNew at the bottom of GenEmptyObj, that is, first new an object, and then read the image data from the bottom of HALCON. You can make a bold guess. At this
insert image description here
time The Key has changed.
Therefore, the judgment of the Key value at the beginning of the Dispose() function is probably to judge whether the Key of the HObject actually points to the underlying image data, and if it is not UNDEF (Zero), it will be cleared.

3 Can directly new object?

If you have seen the WPF template in the HDevelop sample directory, you will find that its image object generation and release do not use GenEmptyObj and Dispose, but the following:

HImage image = new HImage("monkey");
HRegion region;
region = image.Threshold(128, 255);

In addition to the fact that the object is directly new, there seems to be no release code.
In this regard , it is explained in the Quick Guide (Quick Guide) document.
insert image description here
Simply put, HALCON provides two ways of writing. The former (HOperatorSet.GenEmptyObj()) is a procedural (process-oriented) way of writing; while the latter (directly new) It is an object-oriented way of writing.

Then why is the object-oriented writing method, that is, direct new also available? Continue to decompile,
insert image description here
you can see that the constructor executed by new essentially calls the parameterized constructor of the base class with default parameters. Tracing back the underlying code of GenEmptyObj, it can be found that the parameter list of the underlying new object is the same as that of direct new. Therefore, both are equivalent.

As for why Dispose() is not used, I think it is just because this example is not useful. Judging from the results of decompilation, it still needs to be used before each use.


3. Conclusion

After decompilation and analysis, I have a deeper understanding of the application and release of HALCON image object memory. Although it may not be of great help to actual development, it is more confident to use. When using, it is still recommended to strictly follow the requirements in the HALCON document, and try to have a unified style.

A few more caveats:

  • The direct assignment of the image object is a reference assignment, such as
     ho_Img = ho_ImgSrc;
     ho_Img.Dispose();
    
    Such code is potentially dangerous because ho_ImgSrc is also freed without you realizing it.

Guess you like

Origin blog.csdn.net/BadAyase/article/details/130020059