Laden...

AccessViolationException in externer C-lib

Erstellt von Blacal vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.511 Views
B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren
AccessViolationException in externer C-lib

Hallo,

ich kämpfe gerade an einem großen Problem: Ich habe einen Wrapper in C++/CLI für eine C-Bibliothek geschrieben, funktionierte ansich auch immer super.

Seit kurzem habe ich festgestellt, das manchmal beim Aufruf einer Methode eine AccessViolationException auftritt, was ja ansich bedeutet, dass da drinnen irgendwas nicht korrekt mit dem Speicher umgeht.

Nach langem rumprobieren habe ich eine kleines C++/CLI testprogrämmchen geschrieben, welche genau das selbe macht wie mein C# Programm, sprich es greift auf die Library zu, nur halt ohne Wrapper. Hier habe ich bis jetzt noch nie eine Exception bekommen. Das seltsame ist jetzt, wenn ich dieses kleine Testprogrämmchen als dll in ein C# programm einbinde und lediglich die main methode aufrufe, kommt die Exception nach einer Weile wieder.

Meine Vermutung ist jetzt, dass die CLR da irgendeinen Vorgang in der C-lib sieht (und eine Exception auslöst), was das C++ Programm alleine nicht merkt. Problem ist aber nur, dass ich im Moment diese Library umbedingt in C# brauche. Deswegen diese kuriose Frage: Kann man diese Sicherheitsprüfung(en) irgendwie abschalten?

Gruß
Roland

123 Beiträge seit 2008
vor 15 Jahren

Nicht das ich wüsste. Selbst wenn wäre das nicht der richtige Weg.

Marshalst Du irgendwelche Daten ?

Sprich Deinen Wrapper auch mal aus C++/CLI an um sicher zu gehen, das der Wrapper keinen Unsinn baut.

Gelöschter Account
vor 15 Jahren

diese exception tritt auf, wenn unmanaged code versucht auf managed speicherbereiche zuzugreifen oder umgekehrt. deswegen tritt diese exception bei der c++ dll nicht auf.

zeig mal den exceptiontext und die inner exception.

edit:

Eine Zugriffsverletzung tritt bei nicht verwaltetem oder unsicherem Code auf, wenn der Code versucht, in Speicher zu schreiben oder zu lesen, der nicht zugeordnet wurde oder auf den der Code keinen Zugriff hat. Die Ursache hierfür ist i. d. R. ein Zeiger, der einen ungültigen Wert aufweist. Da jedoch nicht jeder Lese- oder Schreibvorgang mit ungültigem Zeiger zu einer Zugriffsverletzung führt, weist das Auftreten einer Zugriffsverletzung darauf hin, dass mehrere Lese- oder Schreibvorgänge mit ungültigen Zeigern ausgeführt wurden und der Speicher möglicherweise beschädigt wurde. Somit sind Zugriffsverletzungen i. d. R. ein Hinweis auf schwerwiegende Fehler in der Programmierung. In .NET Framework, Version 2.0, werden solche Fehler durch das Auslösen einer AccessViolationException-Ausnahme eindeutig gekennzeichnet.

Bei Programmen, die vollständig aus überprüfbarem verwalteten Code bestehen, sind sämtliche Verweise entweder gültig oder NULL. Zugriffsverletzungen sind somit nicht möglich. Eine AccessViolationException-Ausnahme wird daher nur bei Interaktionen zwischen überprüfbarem verwalteten Code und nicht verwaltetem Code oder unsicherem verwalteten Code ausgelöst.

1.361 Beiträge seit 2007
vor 15 Jahren

Hallo Blacal,

Das seltsame ist jetzt, wenn ich dieses kleine Testprogrämmchen als dll in ein C# programm einbinde und lediglich die main methode aufrufe, kommt die Exception nach einer Weile wieder.

Das ist wirklich seltsam, weil wenn du nur die Main-Methode (ohne jegliche Parameter) aufrufst, dann solltes ja garkeine Inteferenzen zwischen einem managed-Speicher und dem unmanaged geben.
Alles was die C++/DLL macht, geschieht im unmanaged Speicher, und die DLL allein läuft ja auch. Sogesehn kann die DLL ja garnicht wissen, wo ihr Aufrufer im Speicher liegt. Außer der watschelt irgendwie den Aufruf-Stack zurück durch.

Oder übergibst du vielleicht doch irgendwo an die C/C++ DLL Verweise auf Objekte/Arrays?
(C# Objekte sind nämlich von Hause aus variabel im Speicher, werden also hin und her verschoben, damit der RAM nicht fragmentiert)

beste Grüße
zommi

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

hmm.. das kommt also wenn unmanaged auf managed zugreifen will (oder umgekehrt). Interresant zu wissen. In dem c++ testprogrämmchen nutz ich auch noch ein bisschen dotnet, beschrängt sich aber z. B. auf aufrufe der Threading API usw.. Nix was mit der C-Library direkt in berührung kommt.

In dem c++ progrämmchen übergebe ich der Bibliothek nix verwaltetes. Das war auch meine hauptabsicht dahinter.

In .NET Framework, Version 2.0, werden solche Fehler durch das Auslösen einer AccessViolationException-Ausnahme eindeutig gekennzeichnet.

Wenn das so stimmt heißt das ja auch gleichzeitig, dass nicht-dotnet-code diesen fehler nicht erkennt, und würde somit meine Vermutung untermauern, oder?

Ich habe den Fehler und das Testprogrämmchen mal zum Urheber dieser Bibliothek geschickt. Mal schaun, ob da was raus kommt.

[Edit]
Was mir grad einfällt. In einer Callback methode greife ich auf ein verwaltetes, statischen objekt zu. Kann soetwas diesen Fehler hervorrufen?

Gelöschter Account
vor 15 Jahren

ja.

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

warum?
Wenn es statisch ist, müsst ich doch problemlos drauf zugreifen können, oder?
Also generell sieht das in etwa so aus:


public ref class TestClass
{
public:
    static List<String^>^ StaticList;
};

int CallBackMethod(...)
{
    StaticList.Add(...)
}

Gelöschter Account
vor 15 Jahren

ja aber für diese struktur wir im geschützten bereich speicher reserviert und wenn eine unmanaged dll darauf zugreifen möchte, muss das entweder speziell erlaubt oder in einen bereich kopiert werden, wo das erlaubt ist.

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

was konkret bedeuted.... (sprich, wie muss sowas dann aussehen, damit es funktioniert?)

Gelöschter Account
vor 15 Jahren

beim valuetype sollte ein out oder in oder beides zusammen reichen.
beispiel:


public static extern void foo([out,in]mystruct valuetype);

das natürlich beim aufruf einer unmanaged methode.

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

hm.. versteh ich jetzt net ganz.
Ich bin ja in C++/Cli, nicht in C#. Und Managed referenzen werden sowieso nie in die C-Lib übergeben.

Es handelt sich lediglich um eine Callback methode, welche in C++/CLI implementiert ist und von dort aus auf eine statische, verwaltete Methode zugreift. Generell versteh ich deinen Gedanken schon, aber was mir jetzt fehlt, ist, wie man das dann in C++/CLI richtig macht.

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

Also, zunächst mal sorry for doppelpost.

Ich hab das jetzt mal nochmal mit meinem C++ testprogrämmchen ausprobiert, also quasi ohne irgendwelche Managed aufrufe von der Callback methode aus: Die Exception kommt trotzdem.

Gelöschter Account
vor 15 Jahren

jetzt wird es dem lesen von kaffeesatz ähnlich. du wirst das problem stück für stück eingrenzen müssen.

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

ich bin eigendlich wieder da, wo ich angefangen habe.

Meine Vermutung ist, dass es sich schlicht um einen Fehler in dieser Bibliothek handelt, weil:

  • die Exception immer an der selben stelle auftritt, nur halt sehr selten
  • das ganze nur in der .Net Umgebung auftritt (vieleicht wurde es ja damit noch nie getestet)
  • die Exception in 2 total unterschiedlichen programmen kommt (meine eigentliche Anwndung und das Testprogramm)

Also wieder zu meiner Frage am Anfang: Kann man den irgendwie dazu bringen dass der die Exception einfach nicht wirft?

Gelöschter Account
vor 15 Jahren

das ist ein sicherheitskonzept von .net. damit wird sichergestellt das unmanged code keinen schabanak mit managed code anstellen kann.

aber fangen wir doch mit dem eingrenzen an:
du sagst das du an keiner stelle irgendetwas an die lib übergibst?
du sagst weiterhin das die lib an keiner stelle etwas von der managed application besitzt?
der trigger ist immer die managed application?

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

ja, die lib bekommt grundsätzlich nix, was managed ist. Wär auch unsinnig.

du sagst das du an keiner stelle irgendetwas an die lib übergibst?

nichts, was managed ist. Alles, wie z. B. strings usw. wandel ich vorher in die jeweils benötigten c-typen um.

du sagst weiterhin das die lib an keiner stelle etwas von der managed application besitzt?

ja, wär auch unsinning, wenn die c lib irgendwelche managed referenzen hält, oder?

der trigger ist immer die managed application?

Der trigger ist nicht immer die managed application. Ich muss ich eine Callback methode registrieren (wird ganz normal in C++ implementiert). In meiner Implementierung rufe ich dann wieder Managed code auf, sollte aber in C++/CLI kein problem sein (dies ist der schon weiter oben erwähnte Fall).

Gelöschter Account
vor 15 Jahren

vielleicht greift die dll in sich selbst von verwaltetem auf unverwaltetem code zu, da man ja in c++/cli unmanaged und managed mischen darf.

B
Blacal Themenstarter:in
387 Beiträge seit 2005
vor 15 Jahren

In meinen Wrapper selbst gibts es durchaus sprünge zwischen managed und unmanaged (ist ja auch seine aufgabe). Die sollten aber allesamt ok sein.

Wie gesagt, der Fehler kommt immer an der gleichen Stelle, und das ist ein einzelner Funktionsaufruf ohne irgendwelche parameter.

Gelöschter Account
vor 15 Jahren

offensichtlich ist da nciht alles ok.