[Erledigt] Probleme mit unsigned char*

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

[Erledigt] Probleme mit unsigned char*

Beitrag von dazedly »

Ich bin leider gezwungen eine in c geschriebene API zu benutzen, welche massenweise mit unsigned char* arbeitet. Jetzt muss ich mir diese rohdaten zwischenspeichern und später wieder verwenden. Wenn ich jetzt Konstruktor oder in einer funktion die Daten übergebe kann ich drauf zugreifen und damit arbeiten, aber wenn ich sie später in einer anderen Funktion abrufe sind sie nicht mehr verfügbar und ich bekomme ein segfault.

Code: Alles auswählen

FPrint::FPrint(unsigned char* data, unsigned int length, QObject* parent): QObject(parent)
{
	this->fprintData = data;
	this->fprintDataLength = length;

}

unsigned char* FPrint::getFprintData()
{
	unsigned int i = 0;
	while(i<getFprintDataLength())
	{
		qDebug() << fprintData[i]; // SEGFAULT!
 		i++;
	}
	return this->fprintData;
}
this->fprintData ist wie zu sehen ist ein unsigned char*. Ich hab auch schon versucht das Ganze in einem QByteArray zu speichern, nur hatte ich da den selben Effekt. Wie kopiere ich die Daten richtig und verhindere, dass andere sie löschen können?


Nachtrag:

Wenn ich folgendes mache, kann ich zwar noch auf Daten zugreifen, aber die sind leider Schrott:

Code: Alles auswählen

	this->fprintData = QByteArray((const char*)data,length);
Zuletzt geändert von dazedly am 15. April 2012 13:55, insgesamt 1-mal geändert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Probleme mit unsigned char*

Beitrag von franzf »

Ich tippe darauf, dass du irgendwo zwischen Initialisierung und getFprintData eine temporäre Kopie dieses FPrint-Objektes erstellt, das auch vor allem wieder zerstört wird. Im Destruktor gibst du fprintData wieder frei. Dein Problem wird ein falsch implementierter/fehlender Kopierkonstruktor/operator= sein.

// edit:
Dein Nachtrag gibt mir wahrscheinlich recht. Kannst du in die Richtung (Destruktor, ope=, CopyCTor) mal Code posten?
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Re: Probleme mit unsigned char*

Beitrag von dazedly »

Den copy gibt es nicht und im destruktor steht nichts, da keiner der member pointer sind. Mein Object lebt auch die ganze Zeit über als Pointer, deswegen schließe ich ein verfrühtes löschen aus. Der segfault würde ja schon beim Zugriff aufs Objekt kommen.

Ich hab jetzt mal das Ganze durch ne Schleife gejagt und miteinander verglichen. Den alten Fehler bin ich los.

Code: Alles auswählen

FPrint::FPrint(unsigned char* data, unsigned int length, QObject* parent): QObject(parent)
{
	this->fprintData = QByteArray((const char*)data,length);
	this->fprintDataLength = length;
	this->error = FPrint::NoError;
	
	unsigned int i = 0;
	while(i<length){
		qDebug() << data[i] << fprintData.data()[i];
		
		i++;
	}
}

unsigned char* FPrint::getFprintData()
{
	return (unsigned char*)this->fprintData.data(); // funktioniert jetzt so wie es aussieht.
}

Ich muss jetzt nur noch rausfinden, warum die C-Funktiuon nichts mit meinen Daten anfangen will.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Probleme mit unsigned char*

Beitrag von franzf »

Ouch... Wieso nimmst du einen Container, der char+ speichert, um darin unsigned char* zu speichern? Dazu diese casts (Frage: weißt du, was genau du da treibst?)
Nimm doch einfach std::vector.
http://www.cplusplus.com/reference/stl/vector/vector/
Du willst den dritten Konstruktor (den mit den iteratoren). Im Beispiel ist das die Zeile 18, wobei du die Größe nicht berechnen musst, du hast sie ja schon:

Code: Alles auswählen

std::vector<unsigned char> ustr(data, data + length);
Trotzdem:
Irgend etwas muss dir deinen Zeiger kaputt gemacht haben, auch wenn es kein Destruktor war. Hat deine C-API irgend welche Methoden zum Aufräumen, die du aufrufst?
Am besten wäre es, du könntest ein minimales Beispie zusammen schustern, oder wenigstens die komplette FPrint-Klassendefinition + alle Methodendefinitionen posten, ebenso die relevanten Methoden (komplette Definition derselbigen), die das nachher kaputte FPrint-Objekt zwischen die Finger bekommen. natürlich Stand VOR dem unsäglichen Versuch mit dem QByteArray...
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Re: Probleme mit unsigned char*

Beitrag von dazedly »

Es funktioniert jetzt soweit alles.
Ich bin nicht so bewandert was C angeht. Ich habs jetzt zum Laufen gebracht. DIe c funktion hat nicht meine Daten bemeckert (hat nichts bemeckert) sondern eher den Falschen Parameter den ich mit übergben habe.

Code: Alles auswählen

	/**
	\brief Adds FMD to enrollment operation.

	Add an FMD to the pool of FMDs for enrollment and return a flag indicating when the enrollment is ready.
	This function must be called before dpfj_create_enrollment_fmd.

	\param fmd_type       type of the FMD.
	\param fmd            pointer to the FMD data.
	\param fmd_size       size of the FMD data.
	\param fmd_view_idx   index of the view
	\return DPFJ_SUCCESS:                  FMD added, enrollment is ready.
	\return DPFJ_E_MORE_DATA:              FMD added, more FMDs for enrollment required.
	\return DPFJ_E_INVALID_PARAMETER:      One or more parameters passed are invalid.
	\return DPFJ_E_ENROLLMENT_NOT_STARTED: Enrollment is not started.
	\return DPFJ_E_FAILURE:                Unknown error.
	*/
	int dpfj_add_to_enrollment(
		DPFJ_FMD_FORMAT  fmd_type,
		unsigned char*   fmd,
		unsigned int     fmd_size,
		unsigned int     fmd_view_idx
	);
Ich hatte immer nur den "DPFJ_E_FAILURE" bekommen, was das Problem natürlich nicht wirklich aufgezeigt hat.

Body

Code: Alles auswählen

#include "fprint.h"
#include "fprintmanager.h"
#include <dpfpdd.h>
#include <stdexcept>
#include <QDebug>
#include <qpixmap.h>
#include <qpainter.h>

FPrint::FPrint(unsigned char* data, unsigned int length, QObject* parent): QObject(parent)
{
	this->fprintData = QByteArray((const char*)data,length);
	this->fprintDataLength = length;
	this->error = FPrint::NoError;
	this->fmd = NULL;
}



FPrint::~FPrint()
{

}

unsigned char* FPrint::getFprintData()
{
	return (unsigned char*)this->fprintData.data();
}

unsigned int FPrint::getFprintDataLength()
{
	return this->fprintDataLength;
}

FPrint::Error FPrint::getError()
{
	return this->error;
}


FPrintFmd* FPrint::getFmd()
{
	if(!this->fmd)
	{
		FPrintFmd *tmpFmd = new FPrintFmd(this);
		tmpFmd->createFmdFromFid(this->getFprintData(),this->fprintDataLength);
		this->fmd = tmpFmd;
	}
	return this->fmd;
}

Header

Code: Alles auswählen


#include "fprint.h"
#include "fprintmanager.h"
#include <dpfpdd.h>
#include <stdexcept>
#include <QDebug>
#include <qpixmap.h>
#include <qpainter.h>

FPrint::FPrint(unsigned char* data, unsigned int length, QObject* parent): QObject(parent)
{
	this->fprintData = QByteArray((const char*)data,length);
	this->fprintDataLength = length;
	this->error = FPrint::NoError;
	this->fmd = NULL;
}



FPrint::~FPrint()
{

}

unsigned char* FPrint::getFprintData()
{
	return (unsigned char*)this->fprintData.data();
}

unsigned int FPrint::getFprintDataLength()
{
	return this->fprintDataLength;
}

FPrint::Error FPrint::getError()
{
	return this->error;
}


FPrintFmd* FPrint::getFmd()
{
	if(!this->fmd)
	{
		FPrintFmd *tmpFmd = new FPrintFmd(this);
		tmpFmd->createFmdFromFid(this->getFprintData(),this->fprintDataLength);
		this->fmd = tmpFmd;
	}
	return this->fmd;
}


Ich hatte vorher QByteArray::fromRawData( const char * data, int size ) [static] benutzt. Das war natürlich nicht gut, weil das auch nur auf das Original gezeigt hat.
Intern benötige ich Streambare member(QDataStream unterstützt den Typ auch nicht) und greife auch deswegen auf QByteArray zurück. Nur brauche ich für diverse Funktionen das unsigned char* und muss deswegen casten.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Probleme mit unsigned char*

Beitrag von franzf »

Deshalb ist ja die std::vector<unsigned char> Variante so schön. Sie hält ein Array aus unsigned char-Werten, und du kannst es jederzeit direkt als unsigned char-Array haben (bzw als "Zeiger auf x. Element in einem Array):

Code: Alles auswählen

std::vector<unsigned char> ustr(data, data + length);
unsigned char* d = &ustr[0];
Siehst du? Komplett ohne casts, ohne Container, der eigentlich auf einen anderen Typ ausgelegt ist, usw.

Und dein Code ist leider nur der mit QByteArray. Ich nehme an, die unsigned char*-Variante hat sich nicht so sehr unterschieden (wär trotzdem wichtig).
Was aber fehlt ist der Header der Klasse und vor allem die Funktion, in der du das FPrint-Objekt verwendest, und in der das Objekt plötzlich einen "kaputten" Array hält. Generell ist das nämlich kein Problem (wenngleich die std::vector-Variante ungleich sicherer und eleganter ist).
Also: wenns dich interessiert, was du falsch gemacht hast, brauchen wir noch mehr (relevanten) Code.
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Re: Probleme mit unsigned char*

Beitrag von dazedly »

Ups hatte zweimal den Body gepostet...

Code: Alles auswählen

#ifndef FPRINT_H
#define FPRINT_H
#include <QByteArray>
#include <QObject>
#include <dpfj.h>
#include <dpfpdd.h>
#include "fprintfmd.h"

class FPrint
{
	public:
		enum FingerType{
			UnknownFinger=DPFJ_POSITION_UNKNOWN,
			LeftThumb=DPFJ_POSITION_LTHUMB,
			LeftIndex=DPFJ_POSITION_LINDEX,
			LeftMiddle=DPFJ_POSITION_LMIDDLE,
			LeftRing=DPFJ_POSITION_LRING,
			LeftLittle=DPFJ_POSITION_LLITTLE,
			RightThumb=DPFJ_POSITION_RTHUMB,
			RightIndex=DPFJ_POSITION_RINDEX,
			RightMiddle=DPFJ_POSITION_RMIDDLE,
			RightRing=DPFJ_POSITION_RRING,
			RightLittle=DPFJ_POSITION_RLITTLE
			};
			
		enum Error {
			NoError=0,
			InvalidDevice=DPFPDD_E_INVALID_DEVICE,
			InvalidParameter=DPFPDD_E_INVALID_PARAMETER,
			Unknown=DPFPDD_E_FAILURE,
			DeviceError=DPFPDD_E_DEVICE_FAILURE
		};
		explicit FPrint(unsigned char* data,unsigned int length);
		virtual ~FPrint();
		unsigned char* getFprintData();
		unsigned int getFprintDataLength();
		FPrint::Error getError();
		FPrintFmd getFmd();
		static QString getFingerTypeName(FPrint::FingerType);
	private:
		QByteArray fprintData;
		unsigned int fprintDataLength;
		FPrint::Error error;
		FPrintFmd fmd;
};

#endif // FPRINT_H
Ich kann dir leider keinen funktionierenden Minimalcode geben, da das ein kleiner Teil von meiner recht umfangreichen API ist. Es läuft ja jetzt auch ganz gut.
Ich danke dir aber für deine Tipps, aber mich würde noch interessieren, ob der Vector sich streamen lässt. Und vor allem wie befülle ich das Ding mit nem unsigned cahr*. Muss ich das durch eine Schleife jagen und einzelne Inserts machen?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: [Erledigt] Probleme mit unsigned char*

Beitrag von franzf »

Es gibt keine operator<</>> Überladung für std::vector. Aber du kannst doch problemlos eine für std::vector<unsigned char> anbieten. Oder noch besser: Das gesamte C-Interface (soweit du es brauchst) in einer Klasse wegkapseln, und dann für DIESE Klasse den op<</>> anbieten.
Antworten