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


von Philipp G. (flashmaster)


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
1
//Imagebuffer auslesen & abspeichern
2
    unsigned char *buffer=NULL;
3
    buffer = new unsigned char [50688];
4
    FILE* fp;
5
    fp=fopen("buffer.txt", "w");
6
    int j,l=0,k=0;
7
    for(j=0;j<50688;j++)
8
    {
9
        k++;
10
        buffer[j] = *(imagebuffer+j);
11
        fprintf(fp,"%d",buffer[j]);
12
        fprintf(fp," ");
13
        if(k==176)
14
        {
15
            fprintf(fp,"\n");
16
            k=0;
17
            l++;
18
        }
19
    }
20
    fclose(fp);
21
    delete[] buffer;

PS: Programmiere mit Visual Studio 2010 (full)

von Peter (Gast)


Lesenswert?

wie gross ist denn der speicher von imagebuffer und wo wird er angelegt?

von besucher (Gast)


Lesenswert?

Von welchem Typ ist imagebuffer und wo zeigt der Pointer hin?

von Philipp G. (flashmaster)


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

von Stefan B. (stefan) Benutzerseite


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).

von Rufus Τ. F. (rufus) Benutzerseite


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?

von Karl H. (kbuchegg)


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.

von Philipp G. (flashmaster)


Lesenswert?

Erstmal hier die Codestelle an dem der globale Pointer den Wert bekommt:
1
BGAPI_RESULT BGAPI_CALLBACK imageCallback( void * callBackOwner,BGAPI::Image * pImage )
2
{
3
    printf("Image received!");
4
    BGAPI_RESULT res = BGAPI_RESULT_OK;
5
    pImage->get( &imagebuffer );
6
    if( res != BGAPI_RESULT_OK )
7
        printf( "setImage failed with %d\n", res );
8
    return res;
9
}


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).

von Rufus Τ. F. (rufus) Benutzerseite


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".

von Nico22 (Gast)


Lesenswert?

... und bitte einmal die Zeile, wo du die Funktion aufrufst.

von Philipp G. (flashmaster)


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.

von Karl H. (kbuchegg)


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.

von Nico22 (Gast)


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.

von Philipp G. (flashmaster)


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?

von Karl H. (kbuchegg)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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?

von Philipp G. (flashmaster)


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

von Philipp G. (flashmaster)


Lesenswert?

So, habe meinen Code jetzt folgendermaßen geändert:
1
BGAPI_RESULT BGAPI_CALLBACK imageCallback( void * callBackOwner,BGAPI::Image * pImage )
2
{
3
  BGAPI_RESULT res = BGAPI_RESULT_OK;
4
  unsigned char* imagebuffer = NULL;
5
  pImage->get( &imagebuffer );
6
7
  FILE* fp;
8
  fp=fopen("buffer.txt", "w");
9
  int j,l=0,k=0;
10
  for(j=0;j<50688;j++)
11
  {
12
    k++;
13
    callbackbuffer[j] = *(imagebuffer+j);
14
    fprintf(fp,"%d",callbackbuffer[j]);
15
    fprintf(fp," ");
16
    if(k==176)
17
    {
18
      fprintf(fp,"\n");
19
      k=0;
20
      l++;
21
    }
22
  }
23
  fclose(fp);
24
  fflush( stdout );
25
  
26
  if( res != BGAPI_RESULT_OK )
27
    printf( "setImage failed with %d\n", res );
28
  return res;
29
}

Leider bleibt der Fehler.
MfG

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Irgenwas ist da dich faul...
1
if( res != BGAPI_RESULT_OK )
2
printf( "setImage failed with %d\n", res );
Was soll die Zeile bringen? res ist ein Konstanter Wert, eigentlich 
müßte da der COmpiler warnen!
1
BGAPI_RESULT BGAPI_CALLBACK imageCallback( void * callBackOwner,BGAPI::Image * pImage ) {
2
    printf("Image received!");
3
    BGAPI_RESULT res = pImage->get( &imagebuffer );
4
    if( res != BGAPI_RESULT_OK ) {
5
        printf( "setImage failed with %d\n", res );
6
    } else {
7
       printf( "Data is now valid" );
8
    }
9
    return res;
10
}
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...

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Läubi .. (laeubi) Benutzerseite


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.

von Philipp G. (flashmaster)


Angehängte Dateien:

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sieh Dir mal die Funktionen getBufferLength und getImageLength an.

von besucher (Gast)


Lesenswert?

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

von Philipp G. (flashmaster)


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

von Stefan B. (stefan) Benutzerseite


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/psteiner/zimpol3/bcs/ds/baumer/Baumer_Programmers_Guide_v10e.pdf

http://webcache.googleusercontent.com/search?q=cache:u9bADc3MUnAJ:ftp://ftp.elvitec.fr/Baumer/SDK/11008819_SW_Baumer_GAPI_SDK_GigE_Win_v1.6.2/Components/Windows32/BGapi/BGAPI%2520SDK/Dev/Example/C%2B%2B/bgapi_capture/bgapi_capture.cpp+BGAPI_RESULT+BGAPI_CALLBACK

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.