Laden...

Kommunikation per JSON Strings: Attempted to read or write protected memory

Erstellt von HerrOli vor 12 Jahren Letzter Beitrag vor 12 Jahren 3.000 Views
Thema geschlossen
H
HerrOli Themenstarter:in
16 Beiträge seit 2011
vor 12 Jahren
Kommunikation per JSON Strings: Attempted to read or write protected memory

Hallo
ich habe ein Messprogramm programmiert. Das Programm besteht aus einer C++ und einem C#Teil. Die Kommunikation zwischen den beiden Teilen erfolgt über JSON String.


for (int i = 1; i <= anzahl_messungen; i++)
            {
                string messwerte = StringReturnAPI01();         

                Console.WriteLine("\nMessung: " + i);
                Console.ForegroundColor = ConsoleColor.Blue;
                Console.WriteLine(messwerte);
                Console.ResetColor();
                
                // teil json string -> objekt
                JsonString JsonObjekt = new JsonString(messwerte);
                
                // ausgabe json objekt
                foreach (var werte in JsonObjekt.MesswerteArray)
                {
                    js_obj.Add(werte.ToString().Replace(Environment.NewLine, ""));
                }
            }

Nun bekomme ich aber in der Zeile JsonString JsonObjekt = new JsonString(messwerte); die Meldung: > Fehlermeldung:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Hier noch der DllInport:



class Messung
    {
        [DllImport(@"Pfad zu C++ dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.LPStr)]
        public static extern string StringReturnAPI01();

        [STAThread]
        public static void Main()

An was könnte den der Fehler liegen?

PS: Ich verwende VS2008 und die JSON Library von http://json.codeplex.com/

C
1.214 Beiträge seit 2006
vor 12 Jahren

Am besten auch gleich den betreffenden C++ Teil posten, zumindest die Methodensignatur und wie du den String erstellst und zurückgibst. So kann man nicht sagen, ob das zusammenpasst.

1.130 Beiträge seit 2007
vor 12 Jahren
 [return: MarshalAs(UnmanagedType.LPStr)]  
        public static extern string StringReturnAPI01();  

Nur mal so aus neugierde: Wie sorgst du dafür, dass der speicher für den LPStr wieder freigegeben wird? Wie allokierst du ihn?

Benutzt du json ausschließlich für interop? Ist eher ungewöhnlich aber ok.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

H
HerrOli Themenstarter:in
16 Beiträge seit 2011
vor 12 Jahren

Mein C++ Teil


extern "C" __declspec(dllexport) char*  __stdcall StringReturnAPI01()
{	
	meas();
	int laenge;	
	char *sc_temp = new char [2];
	char *rscp_temp = new char [5];
	//char *iscp_temp = new char [5];
		
	strcpy(szSampleString,"{\"db\":{\"measurements\":[");	
	
	for(i;i<=messreihe-1;i++)
	{
		mw=true;
		strcat(szSampleString,"{\"RSCP\":");
		_gcvt(vecwerte[i].rscp , 5, rscp_temp);	
		strcat(szSampleString,rscp_temp);
		rscp_temp[0]='\0';		
		strcat(szSampleString,",\"SC\":");
		_itoa(vecwerte[i].sc, sc_temp,10);
		strcat(szSampleString,sc_temp);
		
		sc_temp[0]='\0';
		strcat(szSampleString,"},");	
	}
	
	ULONG  ulSize = strlen(szSampleString) + sizeof(char);
	char*  pszReturn = NULL;
 
	pszReturn = (char*)::GlobalAlloc(GMEM_FIXED, ulSize);
	
	if(mw==true)
		szSampleString[strlen(szSampleString)-1]='\0';	
	
	// Copy the contents of szSampleString
	// to the memory pointed to by pszReturn.
	strcpy(pszReturn, szSampleString);
	
	strcat(pszReturn,"]}}");	

	return pszReturn;
}

Habe mich im bei meinem Programm an diesem Beispiel gehalten: Returning Strings from a C++ API to C#

C
1.214 Beiträge seit 2006
vor 12 Jahren

Du schreibst, dass der Fehler in der Zeile

JsonString JsonObjekt = new JsonString(messwerte);

auftritt. Kannst du denn mit dem Debugger in den String reinschauen, ist er richtig?

1.130 Beiträge seit 2007
vor 12 Jahren

Ich habe eine idee, wie dein fehler kommt.

1.) Deine bibliothek muss eine free-funktion zur verfügung stellen!

extern "C" __declspec(dllexport) char*  __stdcall StringReturnAPI01()
{
....
}

extern "C" __declspec(dllexport) void __stdcall FreeString(char* string)
{
   //todo
}

2.) char* in c++ ist immer Ansi und CharSet.Auto wird standardmäßig unicode. Unicodestrings werden mit 2 nullbytes beendet. Ansi-strings haben aber nur 1 nullbyte. Deshalb wird über das Ende hinaus gelesen und du kiregst ne Access Violation.
3.) Wenn du kein memoryleak haben willst musst du das mashalling eh selber machen.


        [DllImport(@"Pfad zu C++ dll", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr StringReturnAPI01();


        [DllImport(@"Pfad zu C++ dll", CallingConvention = CallingConvention.StdCall)]
        public static extern void FreeString(IntPtr ptr);


IntPtr lpstr=StringReturnAPI01();
string result=Marshal.PtrToStringAnsi(lpstr);
FreeString( lpstr);

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

H
HerrOli Themenstarter:in
16 Beiträge seit 2011
vor 12 Jahren

Ok Danke
Werde ich morgen Testen

H
HerrOli Themenstarter:in
16 Beiträge seit 2011
vor 12 Jahren
  
IntPtr lpstr=StringReturnAPI01();  
string result=Marshal.PtrToStringAnsi(lpstr);  
FreeString( lpstr);  
  

Hallo
Bin gerate am Testen,
eine frage die letzten drei Zeilen verstehe ich noch nicht ganz.
An welcher Stelle muss ich die drei Zeilen genau hinzufügen?

16.806 Beiträge seit 2008
vor 12 Jahren

Kennst Dein eigenen Code nicht?

Vorher:

for (int i = 1; i <= anzahl_messungen; i++)
             {
                 string messwerte = StringReturnAPI01();
 
                Console.WriteLine("\nMessung: " + i);
 

nachher

for (int i = 1; i <= anzahl_messungen; i++)
             {
                 IntPtr lpstr=StringReturnAPI01();
                 string messwerte=Marshal.PtrToStringAnsi(lpstr);
                 FreeString( lpstr);
 
                Console.WriteLine("\nMessung: " + i);
 

würde ich mal stark vermuten...

H
HerrOli Themenstarter:in
16 Beiträge seit 2011
vor 12 Jahren

Das war auch mein erster Gedanke
allerdings kommt dann das StringReturnAPI01() unbekannt ist.

Hatte vielleicht vergessen zu sagen das das mein erstes C# Programm ist
und das ich noch nicht so bewandert in dieser Sprache bin.

Hinweis von herbivore vor 12 Jahren

Wenn du StringReturnAPI01 wie oben beschrieben per DllImport einbindest, sollte der Fehler verschwinden. Bitte beachte auch [Hinweis] Syntaxfehler selbst lösen (Compilerfehlermeldungen) und [Hinweis] Wie poste ich richtig? Punkt 1.1.1. In [FAQ] Wie finde ich den Einstieg in C#? findest du viele weitere nützliche Hinweise.

Thema geschlossen