2016-10-21 1 views
0

Ich arbeite an einer Android-App mit JNI.Probleme mit memcpy auf Android bei Verwendung von Offset für die Quelle

Ich weiter zu senden byte[] von Java und es kommt als jbyteArray in cpp.

Um von der jbyteArray auf eine signed char* i verwenden diese Funktion:

jbyte* content_array = (env)->GetByteArrayElements(array,NULL); 

(jbyte* ist nur ein typedef von signed char*)

Jetzt habe ich auf Probleme stoßen, wenn die Daten zuzugreifen versuchen, auf der Zeiger signed char* zu späteren Zeiten. Es wird angenommen, dass der Java-Garbage-Collector irgendwann loslegt und den Speicher freigibt, so dass ich nicht mehr darauf zugreifen kann.

, um dieses Problem zu umgehen, habe ich jetzt die eingehenden Daten wie folgt kopierte:

// newJavaByteData is the signed char* coming in from java 
    signed char* buffer = new signed char[length]; 
    memcpy(buffer, newJavaByteData, length); 
    //javaByteData is a std::vector<signed char*> 
    javaByteData.push_back(buffer); 

So weit so gut. Bei späteren Bildern kann ich die Daten lesen, und wenn ich es nicht mehr brauchen, ich es wie folgt löschen:

 int frame_cnt=0; 
     while(frame_cnt<javaByteData.size()){ 
      delete javaByteData[frame_cnt++]; 
     } 
     javaByteData.clear(); 

Jetzt muß ich aus diesen Datenblöcken von Bytes extrahieren. Wieder verwende ich memcpy, um den benötigten Teil der Bytes zu extrahieren.

Dieses Mal muss ich eine mit dem Source-Zeiger-Versatz anwenden

char* extractedBytes[lengthOfBytes]; 
    //originalJavaData is the signed char* i did alloc and memcpy into earlier 
    memcpy(extractedBytes, &originalJavaData[offset], lengthOfBytes* sizeof(char)); 

Dieses gut funktioniert, bis seine nicht

:(kann ich Daten auf diese Weise extrahieren, aber wenn die Menge an Bytes extrahieren ich einige Grenze überschreiten, ich bin diesen Fehler.

SIGSEGV (signal SIGSEGV: invalid address (fault address: 0x53)) 

die Fehleradresse mit jeder Zeitnachricht i laufen die App variiert

Ich bin mir noch nicht sicher, was das Limit ist, aber ich kann 262144 Bytes (256x256x4) gerade fein extrahieren, während das Extrahieren von 1048576 Bytes (1024x1024x4) den Absturz/das Signal verursacht.

Ich dachte, das Problem war, dass ich nicht genügend Speicher im cpp-Thread habe, aber ich kann glücklich mehr Speicher zuweisen. nur die memcpy schlägt fehl.

Ich denke, ich könnte einen EventHandler für die SIGSEGV-Signale einrichten, aber ich habe keine Erfahrung damit, und auch ich habe das Problem bis auf die Verwendung von memcpy verfolgt, so hoffe ich es nur eine Sache, die ich falsch mache mit memcpy.

Ich denke, dass es vielleicht ein Problem mit dem Speicher nicht richtig ausgerichtet ist und somit die memcpy fehlschlägt aufgrund der Tatsache, dass ich den Offset zum Quellzeiger hinzufügen.

Jede Hilfe würde sehr geschätzt werden.

+0

Sie müssen dies nicht tun. Die zurückgegebenen Daten können bereits eine Kopie sein und in jedem Fall ist das Ergebnis gültig, bis Sie 'ReleaseByteArrayElements()' aufrufen. Siehe [JNI-Spezifikation] (https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Get_PrimitiveType_ArrayElements_routines). Sie sollten zurückgehen, um Ihr ursprüngliches Problem zu untersuchen. – EJP

+0

Ja. Vielen Dank. Ich habe die Docs erneut angeschaut und festgestellt, dass GetByteArrayRegion bereits für das Kopieren zuständig ist. Ich denke, dass mein Problem wirklich nicht mehr ausreicht ... naja ... noch nachforschen .. – 80prozent

Antwort

0

OK. Ich habe das Problem gefunden.

Es scheint, dass ich den Stapelspeicher knapp wurde, während, wenn ich Heap-Speicher verwenden, ich gut bin zu gehen.

Statt dieser Zeilen:

char* extractedBytes[lengthOfBytes]; 
//originalJavaData is the signed char* i did alloc and memcpy into earlier 
memcpy(extractedBytes, &originalJavaData[offset], lengthOfBytes* sizeof(char)); 

ich habe jetzt das:

char* extractedBytes = new char[lengthOfBytes]; 
//originalJavaData is the signed char* i did alloc and memcpy into earlier 
memcpy(extractedBytes, &originalJavaData[offset], lengthOfBytes* sizeof(char)); 

memcpy jetzt seine Arbeit tut und extrahiert Teile des signed char*, ohne zu klagen.

Natürlich muss ich jetzt durch die Zuweisung des Speichers auf dem Heap darauf achten, meine Daten später zu entsorgen.

Auf eine Nebenbemerkung: Ich habe aufgehört, die eingehenden Daten selbst zu kopieren, und anstelle von GetByteArrayElements verwende ich jetzt GetByteArrayRegion, die das Kopieren für mich macht.

Hoffe, ich werde nicht downvoted für die Beantwortung meiner eigenen Frage erneut. Für mich ist dies eine gültige Lösung für mein Problem.

Verwandte Themen