www.mikrocontroller.net

Forum: PC-Programmierung Buffer auslesen unterbrochen mit Zugriffsverletzung (C++)


Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schönen guten "Morgen",
Ich verzweifel so langsam am meinem Code. Ich möchte ein Imagebuffer 
auslesen von einer Kamera. Es liegen im Buffer mehrere Bilder (176x144 
Pixel, 8bit Grausstufen) hintereinander. Wenn ich meine For-Schleife nur 
bis 25344 laufen lasse (sprich nur ein Bild auslesen möchte) klappt dies 
einwandfrei. Wenn ich jedoch wie unten angegeben zwei Bilder 
gleichzeitig auslesen möchte, kriege ich ein Fehler:

Eine Ausnahme (erste Chance) bei 0x008a1bae in Test4.exe: 0xC0000005: 
Zugriffsverletzung beim Lesen an Position 0x02b98000.
Unbehandelte Ausnahme bei 0x008a1bae in Test4.exe: 0xC0000005: 
Zugriffsverletzung beim Lesen an Position 0x02b98000.
Das Programm "[2980] Test4.exe: Systemeigen" wurde mit Code -1073741819 
(0xc0000005) beendet.

Der Fehler taucht in der Zeile "buffer[j] = *(imagebuffer+j);" auf, wenn 
ich die For-Schleife zum 27497sten Mal durchlaufen möchte.
Habe lange Zeit nicht in C++ programmiert. Habe ich etwas übersehen?
Anbei die "fehlerhafte" Codestelle.

MfG
//Imagebuffer auslesen & abspeichern
    unsigned char *buffer=NULL;
    buffer = new unsigned char [50688];
    FILE* fp;
    fp=fopen("buffer.txt", "w");
    int j,l=0,k=0;
    for(j=0;j<50688;j++)
    {
        k++;
        buffer[j] = *(imagebuffer+j);
        fprintf(fp,"%d",buffer[j]);
        fprintf(fp," ");
        if(k==176)
        {
            fprintf(fp,"\n");
            k=0;
            l++;
        }
    }
    fclose(fp);
    delete[] buffer;

PS: Programmiere mit Visual Studio 2010 (full)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie gross ist denn der speicher von imagebuffer und wo wird er angelegt?

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Von welchem Typ ist imagebuffer und wo zeigt der Pointer hin?

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich programmiere zur Zeit eine 3D-Kamera die zwei Bilder im Buffer 
hinterlegt, einmal ein Graustufen Bild und einmal die 
Tiefeninformationen.
Laut Datenblatt sind zwei Images dort mit 8bit Auflösung gespeichert.
Den Zeiger "imagebuffer" erhalte ich von einer Funktion, die in dem 
"Framework" der Kamera enthalten war.
Die Schleife bricht immer an der selben Stelle ab. Zu dem Zeitpunkt kann 
das zweite Bild aber noch "lange" nicht ausgelesen sein.

Typ von imagebuffer:
unsigned char* imagebuffer

MfG

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider fehlt ein wichtiger Teil des Quelltextes.

1/ Ist imagebuffer vom Typ unsigned char *?

2/ Wie groß ist der Puffer, auf den imagebuffer zeigt?
Ich vermute kleiner als 50688 * sizeof(unsigned char).

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das lässt annehmen, daß "imagebuffer" doch nicht auf so viel Speicher 
zeigt, wie Du annimmst. Hast Du Dir mal im Debugger den Inhalt von 
imagebuffer als Hexdump angesehen?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp G. schrieb:

> Laut Datenblatt sind zwei Images dort mit 8bit Auflösung gespeichert.
> Den Zeiger "imagebuffer" erhalte ich von einer Funktion, die in dem
> "Framework" der Kamera enthalten war.

Wie sieht die Funktion aus?

> Typ von imagebuffer:
> unsigned char* imagebuffer

Zeig mal die Codestelle, wo du dann an den Pointerwert kommst.

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal hier die Codestelle an dem der globale Pointer den Wert bekommt:
BGAPI_RESULT BGAPI_CALLBACK imageCallback( void * callBackOwner,BGAPI::Image * pImage )
{
    printf("Image received!");
    BGAPI_RESULT res = BGAPI_RESULT_OK;
    pImage->get( &imagebuffer );
    if( res != BGAPI_RESULT_OK )
        printf( "setImage failed with %d\n", res );
    return res;
}


An die eigentliche Funktion komme ich nicht herran.
Die Referenz sagt lediglich:

BGAPI_RESULT BGAPI::Image::get  ( unsigned char **  imagebuffer   )

Function category: Retrieve image information. Use this function to get 
a pointer to the begin of image data.

Parameters:  'imagebuffer'  (OUT) Pointer to begin of image data.
Return values:  'BGAPI_RESULT_OK'  No error.


Könnte mir jemand schonmal sagen wie ich im Debugmodus den kompletten 
Wertebereich des imagebuffer einsehen kann (in hex).

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp G. schrieb:
> Könnte mir jemand schonmal sagen wie ich im Debugmodus den kompletten
> Wertebereich des imagebuffer einsehen kann (in hex).

Dazu gibt es im Menü "Debug" den Unterpunkt "Windows -> Memory".

Autor: Nico22 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... und bitte einmal die Zeile, wo du die Funktion aufrufst.

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir wurde gesagt, dass sich diese "Callback" funktion wie eine Art ISR 
(Interrupt) verhält. Sobald Informationen vorhanden sind, wird in diese 
Funktion gesprungen und Zeiger auf die Speicheradresse zugeordnet.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp G. schrieb:
> Mir wurde gesagt, dass sich diese "Callback" funktion wie eine Art ISR
> (Interrupt) verhält. Sobald Informationen vorhanden sind, wird in diese
> Funktion gesprungen und Zeiger auf die Speicheradresse zugeordnet.

Yep. Das sieht erst mal richtig aus.
Die Frage ist allerdings, wie lange dieser Buffer (und damit der 
Pointerwert den du dir holst) Gültigkeit hat. Im schlimmsten Fall müsste 
man von den Daten in der Callback Funktion eine Kopie erzeugen. Das 
würde sich sogar anbieten, da du nur in der Callback Funktion sicher 
sein kannst, dass noch niemand die Bilddaten überschrieben hat (weil die 
Kamera bereits am nächsten Bild arbeitet) (*)

Das andere, wobei es mir die Nackenhaare immer ein wenig aufstellt, sind 
magische Konstanten, wie zb deine 50688

(*) Edit:
Es sei denn natürlich, die Doku sagt etwas anderes.

Autor: Nico22 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun ja, es ist ja fast schon einleuchtend, dass die Bilddaten nur fürs 
Callback gültig sind. Sonst würd die Kiste ja leaken ohne Ende. Aber wie 
Karl Heinz schon sagte: Wenn in der Doku was Anderes steht, ist das 
nunmal so. Aber ich würd davon ausgehen, dass du wirklich eine Kopie 
anlegen musst.

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir grad mal den Speicher angeschaut (wie mir von Rufus t. 
Firefly geraten wurde).
Grob gesagt, mitten im 2ten Bild stehen dort nurnoch Fragezeichen 
anstatt von Hexadezimalen Werten. Somit wurde der Speicher dort 
anscheinend noch nicht beschrieben.

Ich gehe davon aus,dass der Speicher bzw. der Pointer solange gültig ist 
bis ich mir ein neues Bild erzeugen lasse. Im Moment erstelle ich pro 
Programmablauf nur ein Bild (aber 2x144x176 Informationen mit jeweils 
8bit).

MfG
Danke schonmal für eure Mühen/Geduld

@Nico22: Was meinst du mit Kopie?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp G. schrieb:

> Ich gehe davon aus,dass der Speicher bzw. der Pointer solange gültig ist
> bis ich mir ein neues Bild erzeugen lasse.

Ganz wichtig:
Steht das so in der Doku oder ist das eine Annahme von dir?

Hintergrund: Einen Pointer auf irgendwelche Daten rausrücken, ist für 
eine Lib immer ein Hazardspiel, weil sie nicht kontrollieren kann, wie 
lange sich der Aufrufer den Pointer aufhebt.

> @Nico22: Was meinst du mit Kopie?

Na Kopie der Daten!

Der Callback wird aufgerufen, innerhalb der Callback Funktion holst du 
dir den Pointerwert, allokierst selber Speicher und machst eine Kopie 
der Bilddaten. Bei return aus dem Callback kann die Library mit ihrem 
eigenen Buffer machen was sie will, interessiert keinen mehr, du hast 
dir ja die Daten bereits geholt.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp G. schrieb:
> Grob gesagt, mitten im 2ten Bild stehen dort nurnoch Fragezeichen
> anstatt von Hexadezimalen Werten. Somit wurde der Speicher dort
> anscheinend noch nicht beschrieben.

Nicht nur nicht beschrieben, sondern gar nicht vom Prozess vom 
Betriebssystem angefordert.

Zugriffe auf solche Speicherbereiche führen zu einer Exception, und 
deren Resultat ist Deine Zugriffsverletzung.

Bietet denn Deine Kamera-Library keine Funktion, die Aussagen darüber 
trifft, wie groß der Speicherbereich ist, auf den

  pImage->get(&imagebuffer);

einen Pointer liefert?

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ersteinmal zu "Karl heinz Buchegger":
Ich gehe von der Annahme aus, denn die Doku ist eher supoptimal 
geschrieben, da die Kamera noch ziemlich neu ist.

Das mit der Kopie werde ich gleich mal ausprobieren!

Und zu " Rufus t. Firefly":
Leider gibt es solch eine Funktion nicht. Hätte ich auch gerne gahebt 
:-D

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, habe meinen Code jetzt folgendermaßen geändert:
BGAPI_RESULT BGAPI_CALLBACK imageCallback( void * callBackOwner,BGAPI::Image * pImage )
{
  BGAPI_RESULT res = BGAPI_RESULT_OK;
  unsigned char* imagebuffer = NULL;
  pImage->get( &imagebuffer );

  FILE* fp;
  fp=fopen("buffer.txt", "w");
  int j,l=0,k=0;
  for(j=0;j<50688;j++)
  {
    k++;
    callbackbuffer[j] = *(imagebuffer+j);
    fprintf(fp,"%d",callbackbuffer[j]);
    fprintf(fp," ");
    if(k==176)
    {
      fprintf(fp,"\n");
      k=0;
      l++;
    }
  }
  fclose(fp);
  fflush( stdout );
  
  if( res != BGAPI_RESULT_OK )
    printf( "setImage failed with %d\n", res );
  return res;
}

Leider bleibt der Fehler.
MfG

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgenwas ist da dich faul...
if( res != BGAPI_RESULT_OK )
printf( "setImage failed with %d\n", res );
Was soll die Zeile bringen? res ist ein Konstanter Wert, eigentlich 
müßte da der COmpiler warnen!
BGAPI_RESULT BGAPI_CALLBACK imageCallback( void * callBackOwner,BGAPI::Image * pImage ) {
    printf("Image received!");
    BGAPI_RESULT res = pImage->get( &imagebuffer );
    if( res != BGAPI_RESULT_OK ) {
        printf( "setImage failed with %d\n", res );
    } else {
       printf( "Data is now valid" );
    }
    return res;
}
Würde ich erstmal prüfen ob das speichern überhaupt geklappt hat. Ist 
den
imagebuffer überhaupt groß genug um alle Daten aufzunehmen? Den Spciher 
mußt du so wie ich das sehe nämlich selbst anlegen, am besten mit nem 
AutoPtr oder so...

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, dann ist möglicherweise Deine Annahme, daß da zwei Bilder 
hintereinander im Puffer stehen, schlicht und einfach nicht korrekt.

Da die tolle Library anscheinend keine Informationen über in diesem 
Puffer befindliche Daten zur Verfügung stellt, wirst Du die Bilder 
einzeln anfassen müssen.

Du könntest mal -- rein Interessehalber -- die Headerdatei posten, in 
der

   BGAPI::Image

deklariert ist.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:
> Tja, dann ist möglicherweise Deine Annahme, daß da zwei Bilder
> hintereinander im Puffer stehen, schlicht und einfach nicht korrekt.
Es wäre auch denkbar das die Funktion get einfach zweimal hintereinander 
aufgerufen werden muss und jedesmal je ein Bild liefert.

Autor: Philipp G. (flashmaster)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Habe jetzt probiert, dass bei jedem Öffnen der Callback funktion, der 
buffer in ein anderes Array gespeichert wird.
Aber ich lese lediglich das erste Bild aus, weil ich dachte, dass 
vielleicht der Buffer für die beiden Bilder derselbe ist.
Ist leider auch fehlgeschlagen. Habe nun in beiden Arrays ein 
Graustufenbild.

Zu dem Aufbau der Callback-Funktion:
Die habe ich angepasst. Die Beispiele die mitgeliefert wurde waren nur 
für normale Kameras (ohne Tiefeninformation).

MfG


PS: öfter die get-Funktion aufrufen, funktioniert auch nicht.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieh Dir mal die Funktionen getBufferLength und getImageLength an.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass die Kamera noch im falschen Modus arbeitet (2-D) und 
überhaupt keine Tiefenbilder abliefert?

Autor: Philipp G. (flashmaster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus den Funktionen werde ich nicht ganz schlau.

BGAPI_RESULT BGAPI::Image::getBufferLength  ( int *  maxlength,
  int *  minlength,
  int *  currentlength
 )
Function category: Retrieve image information. Use this function to get 
the current buffer length in bytes.
Parameters:
 'maxlength'  (OUT) Maximum buffer length of all existing images formats 
of the connected camera.
 'minlength'  (OUT) Minimum necessary buffer length for the image. This 
buffer length based on the current image format settings of the 
connected camera and is byte exactly calculated.
 'currentlength'  (OUT) Current used buffer length.
Return values:
 'BGAPI_RESULT_OK'  No error.


BGAPI_RESULT BGAPI::Image::getImageLength  ( int *  length   )
Function category: Retrieve image information. Use this function to get 
the image length in bytes.
Parameters:
 'length'  (OUT) Maximum buffer length.
Return values:
 'BGAPI_RESULT_OK'  No error.


Default ist der kombinierte Modus! Und verstellt habe ich eigentlich 
nichts.

MfG

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt Doku und Beispielcode im Netz z.B.

Baumer-GAPI SDK v1.5
Programmer‘s Guide
http://www.astro.phys.ethz.ch/astro1/Users/psteine...

http://webcache.googleusercontent.com/search?q=cac...

pImage->get( &imagebuffer ) legt keinen Puffer an, sondern liefert eine 
zuvor in pImage abgelegte Pufferadresse.

Diesen Puffer muss der Programmierer selbst allozieren und in pImage 
ablegen und nach Benutzung auch wieder freigeben.

Dabei kannst du wählen, ob du ein "Single Image Object" oder "Multiple 
Image Objects" anlegst.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.