Memory access violation after third iteration

Blitz3D Forums/Blitz3D Beginners Area/Memory access violation after third iteration

eos(Posted 2007) [#1]
Hello,

We are starting to develop a 3D software to simulate the anatomic interior of a human being. The anatomical structures may vary their position, aspect and size from one 3D scenario ('person') to another.

We are trying to load that information into custom Blitz types reading it from a a database. Here is an example of our type 'Structure':

Type Estructura
Field estCod% ;code of the structure
Field estNom$ ;name of the structure
Field entEstX% ;x position
Field entEstY% ;y position
Field entEstZ% ;z position
Field entEstEsc% ;a custom scaling
Field m3dCod% ;the code of the respective 3d mesh
Field texCod% ;the code of the respective texture
Field modelo3d.Modelo3D ;the custom type holding the 3d mesh info
Field textura.Textura ;the custom type holding the texture info
End Type

For that purpose, we created an unmanaged dll written in C# to allow the communication between the blitz application and the database.

In the dll we have defined structs equivalent to the Blitz types. Here is the equivalent struct in C#:

public struct Estructura
{
public int estCod;
public string estNom;
public int entEstX;
public int entEstY;
public int entEstZ;
public int entEstEsc;
public int m3dCod;
public int texCod;
public Modelo3D modelo3d;
public Textura textura;
}


To fill the fields of the Blitz type, we instantiate one, set its code field (primary key at the DB) and then pass the type to a dll method (fillEstructura) that receives it by reference and sets every other field with the values obtained by querying the DB using the structure code.

Code in Blitz:

Global estructuras.Estructura[10]

Function traerEstructuras()

For i = 1 To 10
;10 is the number of structures to load (the codes in the DB are correlative, ranging from 1 to 10)

est.Estructura = new Estructura ;************
est\estCod = i
obtenerEstructura(est)
estructuras[i] = es
Next

End Function

Function obtenerEstructura(e.Estructura)

fillEstructura(e) ;here we call the method at the dll

e\estNom = getEstNom(e\estCod)
;sadly, in .NET, strings are not passed well within a referenced struct in an unmanaged environment (?)
;so we set it by calling a dll different function

e\modelo3D = New Modelo3D
e\modelo3d\m3dCod = e\m3dCod
obtenerModelo3D(e\modelo3d) ;similar to the present method for filling the 3D model custom type

e\textura = New Textura
e\textura\texCod = e\texCod
obtenerTextura(e\textura) ;similar to the present method for filling the texture custom type

End Function


Code in C# dll:

[ExportDllAttribute.ExportDll("fillEstructura", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static void fillEstructura(ref Estructura est)
{
string sql = "select * from Estructuras where EstCod=" + est.estCod;

//custom class and function to obtain get a Dataset containing the result of the sql query
DataSet ds = ManejadorBD.getInstance().executeQuery(sql);

if (ds.Tables[0].Rows.Count > 0)
{
DataRow fila = ds.Tables[0].Rows[0];

//fills the attributes of the struct with the proper values
est.entEstX = (int)fila["EntEstX"];
est.entEstY = (int)fila["EntEstY"];
est.entEstZ = (int)fila["EntEstZ"];
est.entEstEsc = (int)fila["EntEstEsc"];
est.texCod = (int)fila["TexCod"];
est.m3dCod = (int)fila["M3DCod"];
}
}


[ExportDllAttribute.ExportDll("getEstNom", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static string getEstNom(ref Estructura est)
{
string retorno = "";
string sql = "select EstNom from Estructuras where EstCod=" + est.estCod;

DataSet ds = ManejadorBD.getInstance().ejecutarQuery(sql);

if (ds.Tables[0].Rows.Count > 0)
{
DataRow fila = ds.Tables[0].Rows[0];
retorno = (string)fila["EstNom"];
}

return retorno;
}


Here are the respective entries at the .decls file:

.lib "Com.dll"
fillEstructura(est*): "fillEstructura"
getEstNom$(est*): "getEstNom"


Everything works fine on the individual tests, I mean when filling one structure at a time. However, when trying to batch process a lot of structures within a for or a while (like in the above blitz code example) the trouble begins: After every third loop of the for, the line marked with the ************ at the code (est.Estructura = new Estructura) generates a Memory Access Violation exception.

Why always after the third one? Why the first two always work fine no matter if you change the step of the for iteration to -1 to exclude an instance related issue? Why after every third time the line is executed and not before????

Please shed some light on this issue!

Thanks in advance for your help.


b32(Posted 2007) [#2]
The Blitz part of the code seems to run fine, so the error is prob. caused in the .dll.
The code itself doesn't look like something is wrong. I didn't knew you could directly fill a type from a .dll.
It is certainly a strange error, if it occurs only after 3 times. Maybe you are writing to a protected memory section somehow?
I would try to read/fill only the EStructura type, without the Modelo3D and Textura (sub)fields?
If you can't get it to work properly, you could maybe merge all the fields into a string and pass that along, or write a separate function for each field, like GetName, GetX, GetY, GetZ etc.


eos(Posted 2007) [#3]
Thanks a lot b32 for your post.

As a matter of fact, your solution (the dll method returning a string with all the values separated by a # character and then parsing the string and filling the type fields at the Blitz side) is what we are using right now as a temporary solution. Nevertheless, we hoped that someone could have experienced the same strange thing and maybe knew how to resolve it. It looks like we will be adopting the string solution as a permanent solution, though. :-)

BTW, we also tried without the type fields and the exception still occurs.

I agree with you about the problem being at the C# side. I am pretty sure if the dll was written in C++ this wouldn't be hapening. The .NET way to manage (or unmanage) some things like pointers and references, really creeps my nerves!

Thanks again for your post.