We had sporadic problems with VO-Code adapted to X# containing structures with byte arrays casted to psz-Variables and passed to functions with psz-Variables in another X#-dll. The origin was a Crystal-Reports C-Dll that called these functions directly. Now the C-Dll sends the data via Windows-Messages to the X#-Program. This is not a nice solution, but we need this possibility as long as we use Crystal Reports with our "plugins" to call X#-program functionality within the Crystal Reports runtime engine.
Somtimes the psz-strings in the final dll were not filled with the data from the origin (parts or nothing). Speed of the program was influencing this behavior. When I ran the program against a database on a fast database server I had more errors than against a slower database with the same data, both programs running on the same machine. I believe that the garbage collector influenced this behavior having more to do with the faster execution, but I have no proof.
Unfortunately I could not reproduce the problem to make a simple test program. But rewriting the code and substituting the psz-vars by X#-String-Vars resolved this issue. So this may be hint for other people: try to substitute as many pointer variables by Dotnet variables.
Arne
Sporadic problems with pointers to psz strings/byte arrays in structures
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Sporadic problems with pointers to psz strings/byte arrays in structures
Arne,
You write that you are casting byte arrays to psz variables.
Can you an example of that code, both on the sending side and the receiving side ?
Robert
You write that you are casting byte arrays to psz variables.
Can you an example of that code, both on the sending side and the receiving side ?
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Sporadic problems with pointers to psz strings/byte arrays in structures
Robert,
I have attached a shortened version of the code before my changes (old) and now (new). The data is written into the structure treating it as a byte structure. Afterwards the data is always correctly interpreted as it is defined in the structure.
I am nearly completely sure that the data arrived always correctly into the structure and that the psz-data within the structure could be interpreted always correctly immediately after receiving the data.
I believe that the reason is that in the old solution pointers with data within a structure were passed to a function and that the memory location of the structure perhaps was moved during Garbage Collection.
In an earlier version (file cryrepfunctionsold.txt line 90) I used a pointer to a psz within the structure as return value: @sCRYREPUFL.cTransform. This sometimes returned false values. Then I changed it to a psz allocated locally and copied the values afterwards to @sCRYREPUFL.cTransform. This resolved the issue.
Afterwards I had sporadically problems with the input value @sCRYREPUFL.cPar1. I passed this as a pointer to a strong typed function "CRYREP_VOShellObjectMethod" with pszs as parameters. Now I make copies of these pszs via usage of psz2string and call the functions/methods with these pointerfree strings.
I believe that when using the value within this function, the pointer was not valid anymore. Probably copying the contents of @sCRYREPUFL.cPar1 and the other strings to pszs allocated locally and passed separately to the function would have worked. Probably also passing the pointer of the structure to the function and then taking the pszs in there would have worked. But surely the best is to convert the pszs as quick as possible to strings and as late as possible back to pszs.
I have attached a shortened version of the code before my changes (old) and now (new). The data is written into the structure treating it as a byte structure. Afterwards the data is always correctly interpreted as it is defined in the structure.
I am nearly completely sure that the data arrived always correctly into the structure and that the psz-data within the structure could be interpreted always correctly immediately after receiving the data.
I believe that the reason is that in the old solution pointers with data within a structure were passed to a function and that the memory location of the structure perhaps was moved during Garbage Collection.
In an earlier version (file cryrepfunctionsold.txt line 90) I used a pointer to a psz within the structure as return value: @sCRYREPUFL.cTransform. This sometimes returned false values. Then I changed it to a psz allocated locally and copied the values afterwards to @sCRYREPUFL.cTransform. This resolved the issue.
Afterwards I had sporadically problems with the input value @sCRYREPUFL.cPar1. I passed this as a pointer to a strong typed function "CRYREP_VOShellObjectMethod" with pszs as parameters. Now I make copies of these pszs via usage of psz2string and call the functions/methods with these pointerfree strings.
I believe that when using the value within this function, the pointer was not valid anymore. Probably copying the contents of @sCRYREPUFL.cPar1 and the other strings to pszs allocated locally and passed separately to the function would have worked. Probably also passing the pointer of the structure to the function and then taking the pszs in there would have worked. But surely the best is to convert the pszs as quick as possible to strings and as late as possible back to pszs.
- Attachments
-
- cryrepfunctionsnew.txt
- (5.04 KiB) Downloaded 54 times
-
- cryrepfunctionsold.txt
- (5.13 KiB) Downloaded 57 times
Sporadic problems with pointers to psz strings/byte arrays in structures
Arne,
I had a quick look and do not see what the problem could be
I would have to compile this and check the generated IL and run it in the debugger.
One thing that could be related is that you are passing addresses to the CRYREP_VOShellObjectMethod() function but the parameters are declared as PSZ.
Robert
I had a quick look and do not see what the problem could be
I would have to compile this and check the generated IL and run it in the debugger.
One thing that could be related is that you are passing addresses to the CRYREP_VOShellObjectMethod() function but the parameters are declared as PSZ.
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Sporadic problems with pointers to psz strings/byte arrays in structures
Robert,
thank you for looking.
For me the issue is resolved. In any case it is important to clean up as much "ugly" code as possible. Nowadays pointer usage makes part of ugly code.
The PSZs gave us many problems in the Past with VO in combination with the Garbage Collector and are a risk in X# similarly. Where PSZs are still necessary, then locally allocated memory should be used or conversions to strings as early as possible.
I remember that we tried to move from VO 2.5 to VO 2.6, but the program got unstable often. Then we tried to move to VO 2.7, and still too unstable. Only with VO 2.8 we received a stable runtime and I believe that most was due to your changes from casting PSZs to proper conversion functions like PSZ2string.
thank you for looking.
For me the issue is resolved. In any case it is important to clean up as much "ugly" code as possible. Nowadays pointer usage makes part of ugly code.
The PSZs gave us many problems in the Past with VO in combination with the Garbage Collector and are a risk in X# similarly. Where PSZs are still necessary, then locally allocated memory should be used or conversions to strings as early as possible.
I remember that we tried to move from VO 2.5 to VO 2.6, but the program got unstable often. Then we tried to move to VO 2.7, and still too unstable. Only with VO 2.8 we received a stable runtime and I believe that most was due to your changes from casting PSZs to proper conversion functions like PSZ2string.
Sporadic problems with pointers to psz strings/byte arrays in structures
Arne
Just a thought.
This is obviously a complex situation. But you mention speed appearing to have something to do with it.
Complexity and Speed always triggers me to think of timings and code locks.
I would suggest that behind the scenes there are probably a number of Asynchronous call backs.
OR possibly some required class is not inhibiting garbage collection - this can easily happen with events and interrupts, although the compiler itself should prevent it.
Terry
Just a thought.
This is obviously a complex situation. But you mention speed appearing to have something to do with it.
Complexity and Speed always triggers me to think of timings and code locks.
I would suggest that behind the scenes there are probably a number of Asynchronous call backs.
OR possibly some required class is not inhibiting garbage collection - this can easily happen with events and interrupts, although the compiler itself should prevent it.
Terry