C#-Assembly in unmanaged C++ - Stackoverflow
-
Vorab einige Infos, wie das erstellte Zeugs aussieht, und was es tun soll:
Es existiert ein sehr großes Programm, welches in C++ geschrieben wurde und seine Funktion erfüllt. Bisher zumindest. Jetzt sollte eine Funktion des Programms massiv überarbeitet und erweitert werden, was meine Aufgabe wurde. Diese Funktion greift auf eine Access-Datenbank zu, holt sich dort meist ein paar tausend Datensätze ab und gibt diese in entsprechender Form als xml aus. Das Ganze funktioniert für sich allein wunderbar - getestet habe ich alles als .exe, allerdings soll daraus eine .dll werden, welche im großen Programm (unmanaged) genutzt und aufgerufen wird. Das Aufrufen funktioniert soweit auch, allerdings fliegt er mir mitten in der .NET-Assembly beim füllen der Tables im DataSet mit einem Stackoverflow raus. Warum, das weiss ich nicht. Abfangen von StackoverflowException funktioniert leider nicht - er läuft in den try-Block und fliegt dann dort mit Stackoverflow weg. Ich hoffe, dass mir hier jemand helfen kann bzw. jemand eine Idee hat, woran das liegen könnte. Wie gesagt, für sich allein läuft die Assembly fehlerfrei und macht genau das, was sie soll (auch mit großen Datenmengen -> xml-Exporte mit teilweise 35-40 MB)
verwendetes Datenbanksystem: Access 97Umgesetzt habe ich das Holen der Datensätze in C# wie folgt:
namespace AdasExport { [ComVisible(true)] [ClassInterface(ClassInterfaceType.AutoDual)] public class AbExport() { public void writeData(int iAnbieter, int iStufe, int iDatumStart, int iDatumEnde) { private DataSet dataSet = new DataSet(); private OleDbConnection oledbConnection = new OleDbConnection(); private OleDbCommand oledbSelectCommand = new OleDbCommand(); private OleDbDataAdapter oledbDataAdapter = new OleDbDataAdapter(); oledbConnection.ConnectionString = @"Data Source = TmpAbda.mdb;" + "Provider = Microsoft.Jet.OLEDB.4.0;"; dataSet.Tables.Add() //wird 8 mal ausgeführt, da ich 8 Tables benötige try { label.Text = "Datenbanken werden gelesen..."; label.Refresh(); proBar.Value = 0; int iSchrittweite = 142; fillDiversTable(); proBar.Value += iSchrittweite; fillLagerTable(); ----> hier fliegt er raus proBar.Value += iSchrittweite; fillLieferungTable(); proBar.Value += iSchrittweite; fillGrosshaendlerTable(); proBar.Value += iSchrittweite; } } //Hier sind natürlich noch viele weitere Funktionen, diese werden zu dem Zeitpunkt aber noch gar nicht angesprungen.
Die Funktion, in der er mir den Stackoverflow erzeugt, sieht so aus:
private void fillLagerTable() { oledbSelectCommand = oledbConnection.CreateCommand(); oledbSelectCommand.CommandText = @"SELECT Lager.diPzn, Lager.iLagNr, Lager.diSpezVk FROM Lager;"; oledbDataAdapter.SelectCommand = oledbSelectCommand; try { oledbDataAdapter.Fill(dataSet.Tables[3]); } catch (Exception ex) { writeFehlerlog(ex); } oledbSelectCommand = oledbConnection.CreateCommand(); oledbSelectCommand.CommandText = @"SELECT LagerOrt.iLagNr, LagerOrt.strBezeich FROM LagerOrt ORDER BY iLagNr;"; oledbDataAdapter.SelectCommand = oledbSelectCommand; try { oledbDataAdapter.Fill(dataSet.Tables[4]); // An dieser Stelle tritt der Stackoverflow auf } catch (Exception ex) { writeFehlerlog(ex); } }
Offenbar führt er also einige Fill-Befehle aus und anscheinend geht ihm da irgendwann der Platz aus. Kommentiere ich den Aufruf der Funktion aus, dann fliegt er mir bei der nächsten raus mit derselben Meldung.
In den Projektoptionen habe ich den Haken bei "Für COM-Interop registrieren" gesetzt, was ja benötigt wird, um die Assembly überhaupt aus unmanaged Code aufzurufen. Hier wird mir dann eine .tlb erstellt, welche ich, zusammen mit der .dll, ins Verzeichnis meiner unmanaged Anwendung kopiere.
Im unmanaged Code gehe ich dann wie folgt vor:
#import "AdasExport.tlb" raw_interfaces_only void PAnVive::StartViveTransfer(BOOL bManuell) { AbExport::_AbExport *pptr; CoInitialize(NULL); GUID dwTest = __uuidof(AbExport::AbExport); AbExport::_AbExportPtr Class1Ptr(dwTest); pptr = Class1Ptr; pptr->writeData_2(1,3,20100601, 20101230); //Stackoverflow innerhalb Assembly }
writeData_2 wird die public-Funktion in C++ genannt, die in C# writeData mit 4 Aufrufparametern heißt. Von dieser existiert noch eine mit 3 Parametern, deshalb wird sie in C++ als Nr. 2 aufgeführt.
Wie gesagt, sobald er in die Assembly springt, werden dort sogar ein paar .Fill-Anweisungen ausgeführt, aber ab einer bestimmten Menge scheint das nicht mehr zu wollen. Erklären kann ich es mir nicht so recht, da das Ding standalone ja funktioniert.
Woran könnte das liegen?
Gruß
-
Warum tust Du es nicht Debuggen um zu sehen wo und warum es zum Stackoverflow kommt?
Simon
-
Habe ich gemacht, aber wirklich sehen kann ich dabei nichts. Ohne weiteren Kommentar bekomme ich eine Stackoverflow-Meldung (aber auch das nicht immer) und weitere Infos spuckt der Debugger nicht aus (bzw. ich habe nicht herausgefunden, wie man noch mehr herausbekommen könnte).
-
Bredley schrieb:
Habe ich gemacht, aber wirklich sehen kann ich dabei nichts. Ohne weiteren Kommentar bekomme ich eine Stackoverflow-Meldung (aber auch das nicht immer) und weitere Infos spuckt der Debugger nicht aus (bzw. ich habe nicht herausgefunden, wie man noch mehr herausbekommen könnte).
Durchsteppen?
-
Jo, so mach ich das auch, mit F5 erst mal den meisten Kram überspringen und dann in Nähe des fraglichen Codeabschnittes mit F10 durchsteppen. Allerdings, wie gesagt, passiert genau dann der kommentarlose Abflug. Aber nur, wenn ich die .dll aus der C++-Anwendung laufen lasse. Lasse ich das Ganze als eigenständige .exe laufen, funktioniert alles so, wie es sein soll.
-
Allerdings, wie gesagt, passiert genau dann der kommentarlose Abflug. Aber nur, wenn ich die .dll aus der C++-Anwendung laufen lasse
Dann tue eben mit F11 in die C# Dll reinsteppen!
Edit:
Ev. fehlt Dir das: http://www.c-plusplus.net/forum/282645