Access Violation with Certain Cameras on Closedown of Delphi GenICam Example

Hello

I am trying to use inspiration from your Delphi tutorial examples to open CVB cameras in our software (you may have seen me mention this in other threads but this is a different issue, hence why I have started a new one!).

To cut a long story short, when you have opened a camera and then close the software in the Delphi debugger, you get the following Access Violation:

image

At first, I thought it might be something I was doing, but then I noticed it also happens in your Delphi STEMMER IMAGING\Common Vision Blox\Tutorial\Hardware\GenICam\Delphi\DelphiGenICamExample.

I have narrowed it down to being something to do with the setup of the NodeMap, as if you remove any reference to setting up a nodemap in a separate, even smaller, test program I have made then it works, but as soon as you put the code back in regarding setting up the NodeMap then you get the error on close down again.

Strangely, this seems to be true for some cameras but not all. We are using a Flir and an Allied Vision, here, and the Allied Vision causes the Access Violation but the Flir doesn’t, despite your code example being the same in both cases! (The Flir one causes a different violation as it struggles to assign the NodeMap to a TCVGenApiGrid, but that isn’t really an issue for us as we’re not going to use one of those, anyway).

(The exact models in question are:
Flir: Blackfly S BFS-U3-16S2M
Allied Vision: Alvium G1-158m)

What can be done with the main issue described of an access violation upon close down with the AV camera, please? It is clear it is causing some sort of “camera cleanup” issue, as when you run the program outside Delphi, although you don’t actually see the an error message, it takes between 30-60 secs for the program to fully clear out of Task Manager.

Thanks

Daniel

Hi @danielquintic

I fear that this is something we will not further investigate if this is only related to Delphi.
If this can be reproduced with one of our current examples without the GenApiGrid ActiveX control in C++, C# or Python this would be of course something we need to look into.

One idea I have left is to remove the GenApiGrid. All access to the Nodemap features in this example is done via the iCVGenApi not the Grid with the functions e.g.:
NMHGetNodeMap
NMGetNode
NGetAsString

They do need the reference to the iCVGenApi but not the CVGenApiGridLib_TLB

Remove the CVGenApiGridLib_TLB from “uses” in the Tutorial and every code line which is referring to it and via the variable cvGenApiGrid.

It’s disappointing that this will not be looked into - Delphi is the language we use and, until this most recent release, as far as I was aware was still supported in the version of CVB we downloaded less than 6 months ago. How long is it since this example was last looked at? I’m reluctant to start looking into examples in other languages as that’s not relevant to us.

As regards removing the GenApiGrid, I have just taken your DelphiGenICamExample and removed the GenApiGrid and CVGenApiGridLib_TLB from “uses” but the violation on close down when using the Allied Vision camera remains. There is no error at all from the Flir, now.

As mentioned in my previous message, I have done an even smaller example program than this, where the error goes away as soon as you remove any reference to a NodeMap, so I’m pretty sure it’s that that is causing the issue. Any further thoughts would be much appreciated, please.

@danielquintic
Besides some minor cosmetic changes the last real change was made more than 10 years ago.
From my point of view this is not important as the error is related to the nodemap access.
Sadly removing the Grid did not help. This would have been an easy solution.

During the last years the GenIcam Standard has changed. Cameras support the new versions of the standard more and more. The AV Alvium is a very new camera. It is possible that it uses features from the new standard which were not available before.

I will discuss this with @illusive if we can do further steps like trying to reproduce it ourselves when we are back from vacation.
From tomorrow on our company is in vacation until the 2nd of January. I am sorry that i do not have better news and that you need to wait for more information until the first week of 2023.

Nevertheless I wish you Merry Christmas and a Happy new Year.

OK - Yes that would be great if you could look into it please as it would be a shame if we have to start writing C++ interfaces etc. as that was the one thing we were trying to avoid when we chose to use CVB in Delphi in the first place.

Could the fact that it’s so old also be a reason why I am struggling to extract time stamps, as discussed on my other thread?

Thank you for your help - We’re also off until the New Year now - have a good Christmas and New Year.

Just as an addition to the Violation issue, I believe this is also causing us problems when trying to open multiple of these Allied Vision cameras in the program.

On our high spec machine here in our office, we can get 7x cameras open with 700 buffers at 1280x584 at 100fps. However, it’s very hit or miss - sometimes it will open all 7, but sometimes only 2 or 3 and then stop. Running this within Delphi, on the occasions where it stops, it actually throws exactly the same error as was shown above, that it otherwise throws on closedown, so clearly some element of memory, seemingly related to the NodeMaps, isn’t being allocated or deallocated properly.

Hi @danielquintic
I wish you a Happy New Year.

In the other post you wrote:

We are already compiling as a 64 bit program

The screenshot with the access violation shows a 32Bit address.
So there are still some open questions:

  • Are you really compiling your application as a 64Bit process
  • Did you try to run your application with a default buffer size of 3? Do you see the issue on opening and closing as well?
  • Which CVB Version do you use?

Happy New Year!

Yes it’s definitely a 64 bit program as 64-bit Windows is selected as the Target Platform in Delphi.
Also, when you run it in Task Manager it doesn’t say “(32 bit)” next to the name.
Also, I managed to get about 6GB of RAM open in it yesterday (more luck than judgement!) but that wouldn’t be possible for a 32 bit application.

As regards running with a default buffer size of 3, please remember these issues are visible in your GenICam example code, which I don’t believe adjusts any of the defaults just by executing.

As regards which CVB version we use, I set up CVB in Delphi using 13.04.005 as that was the latest one at the time I did it. We have tried both 14.00.001 and 13.04.005 as the one installed at run time but there doesn’t really seem to be any difference between the two.

The set up process I describe is the only place I wonder if could be looked at as regards 32 vs 64 bit. Delphi itself only runs as a 32 bit application (perhaps this is why the error address is 32 bit?), so to get the 64 bit CVB package setup, you first have to follow through your instructions to set up the 32 bit version, then recompile that for 64 bit as well. Do you think it’s worth me unpicking that and trying to set up CVB within Delphi again, following the CVB ReadMe instructions from scratch?

Hi @danielquintic and @Sebastian

In an earlier post further up, there was a miconception: The screenshots provided by @danielquintic do not show memory addresses. $c0000005 is the exception code for an access violation - and this will be displayed as a 32 bit value in a 32 bit and a 64 bit process. So we cannot deduce from this screenshot whether the process is running as a 32 bit or a 64 bit process.

However, the symptoms would fit a pointer aliasing bug and I have indeed found one in the DelphiGenICamExample:

In MAIN.pas, line 158ff the following code can be found:

procedure TMainForm.SetupNM;
var AvailableExposureTimeNodeName:AnsiString;
    i                   : LongInt;
    ...
    currentPixelFormatString: AnsiString;
begin
  // get Noadmap from Camera
  if (CanNodeMapHandle(IMG(cvImg.Image))) then
    NMHGetNodeMap(IMG(cvImg.Image), theNodeMap);
  // Set loaded Nodemap to GenApiGrid
  if (IsNodeMap(theNodeMap)) then
  begin
    cvGenApiGrid.NodeMap := LongInt(theNodeMap); // <---- problem!
    ...
    end
end;

What happens here is the following:

  1. The Image property from the cvImg control is used together with NMHGetNodeMap to extract the camer’s node map handle into the variable theNodeMap. theNodeMap is a global variable of type NODEMAP (which is just another way of saying Pointer…).
    cvImg.Image in a 64 bit build is a 64 bit integer (see line 163-169 in CVImageLib_TLB.pas), so this is going to work for 32 and for 64 bit.
  2. In the assignment of theNodeMap to cvGenApiGrid.NodeMap (which is yet another 64 bit property, see line 176-182 of CVGenApiGridLib_TLB.pas) the cast LongInt(theNodeMap) is used to convert the Pointer into an integer. But LongInt is only a 32 bit integer. So if any of the upper 32 bits of theNodeMap was set, the pointer will have been mutilated by this statement.

So unfortunately the example program was not really 64 bit capable - a fact that went unnoticed for more than ten years :frowning:

Can you please replace the LongInt above with an Int64 and let us know to what extent that changes the situation?

The development environment running only as a 32 bit process was a problem we also had with Visual Studio. That is why the x64 installers of :cvb: come with two sets of ActiveX controls:

  • One set that gets installed into the %CVB% directory targeting the x64 architecture
  • One set that gets installed into the %CVB%\Wow6432 directory.
    This set of ActiveX controls is admittedly a bit weird, as it has been built for the Win32 architecture, but has the type library of the x64 controls (with properties like Image or NodeMap modeled as 64 bit integers). The only thing these controls fit for is to enable the development environment to display the controls! The should never be used in production code.

But as pointed out in my previous post, the $c0000005 is not an address in this context, so I do not think that there actually is anything do be done. You should actually be able to see in the form editor that the Image property of cvImg and the NodeMap property of CVGenApiGrid are of type Int64 - if that is the case, you should be fine (as you also already mentioned that the process is not displayed as a 32 bit process by the Windows Task Manager).

Thanks for clarifying what is meant by $c0000005.

As previously stated, I have already deleted the cvGenApiGrid in your example and the problem still occurs.

Your suggestion might solve the problem where I was saying we were getting violations when trying to load a Flir camera into the cvGenApiGrid - that was why I took the cvGenApiGrid out (see previous messages).

But there is now no casting of theNodeMap to a LongInt going on and the problem still happens I’m afraid.

I note that there are various LongInts in the local variables for the SetupNM procedure - should they be changed to int64 as well?

As regards the 32 vs 64 bit environments, I took a complete copy of all the CVB files and it is to that which the library variables are pointed (see screenshot below).

image

Do you mean I need to add the Wow6432 link as well?

Do you think it’s worth me trying to do all those steps from the ReadMe again?

I don’t quite understand your point about not using the controls - what am I meant to do instead?!

Thanks

Daniel

But the problem is still an access violation when closing the software?

No. LongInt is only a problem when casting between pointers and integers (the ActiveX controls’ Image and NodeMap properties are in reality pointers, but have been mapped to integers because do not really know the concept of a pointer to a non-COM object).

Nonono. I was only pointing these out for you to understand how the ActiveX controls interact with the development environment (you correctly stated that the development environment is a 32 bit process and as such cannot instantiate 64 bit controls…).

If you think the state that you had after going through the readme has now been compromised this can’t hurt.

The point is that if you have :cvb: for x64 installed you are technically able to build and launch a 32 bit application. But that application has practically no chances of working properly.

Yes - Imagine taking your DelphiGenICamExample code and deleting the actual cvGenApiGrid object. That will necessarily involve commenting out all the references to it, including the LongInt cast you mention, to allow the program to compile again. Once you have done that, the program will compile and run OK but you still get the close down error with this $c0000005 message.

If you then take that code and further comment out theNodeMap, thereby forcing you to comment out any other lines which relate to theNodeMap until you can compile the example again, you then end up with a program which opens, you can do some grabbing etc, but crucially DOESN’T have the $c0000005 error on closedown. Therefore, the error must be to do with theNodeMap in some way - I think it’s possibly not allocating enough memory space for theNodeMap and so when theNodeMap gets written it “overhangs” the memory space that has been allocated for it.

Thanks for clarifying the other parts. I don’t really believe the package has been compromised since I first did it, as I haven’t touched it, but I guess I could have got something wrong in the first place - I will see.

OK - So basically don’t try to do a CVB 32bit program once you have set up CVB for 64bit in Delphi?

Are there any further thoughts on resolving this Access Violation please as once this is solved, our software should hopefully be complete in terms of CVB functions?

Thanks

Daniel

Hello @Sebastian and @illusive (and anyone else who might be able to help!)

Are there any further suggestions as to how to solve this loadup/closedown memory Access Violation for the Allied Vision cameras, please, as this is now becoming an URGENT issue for continuing progress on our project.

Thanks

Daniel