Forum: Compiler & IDEs CRC byteweise über Struct


von Max Jostkleigrewe (Gast)


Lesenswert?

Hallo,

ich schreibe gerade an einem Sicherheitsrelevanten Programm für meine
Diplomarbeit.
Mein problem ist, dass ich eine Checksumme über ein Struct^2 machen
möchte.

Beispiel :
unsigned long int Function_CRC(BAUM baumvariable);

typedef struct grosser_ast {
  char Blatt[5];
  int  Blattanzahl;
  }grosser_ast;
// 7Byte


typedef struct BAUM{
  grosser_ast Ast1;
  char        Ast2[5];
  int         Astanzahl;
  }BAUM;
//14Byte

int Main(void){

unsigned long int crcvalue;
BAUM Eiche; //14Byte
strcpy(Eiche.Ast1.Blatt,"Grün");
Eiche.Ast1.Blattanzahl=2;
strcopy(Eiche.Ast2,"Braun");
Eiche.Astanzahl=2;
crcvalue=Function_CRC(Eiche);
}


das CRC wird schematisch wie folgt berechnet:

unsigned long int Function_CRC(BAUM baumvariable){
for (i=0;i<14;i++){//weil baumvariable 14Byte
checksum = (checksum >> 8) ^ crc_table[*(&baumvariable+i) ^ (checksum &
0xff)];}
retur checksum;
}

hat vielleicht jemand eine Idee, wie ich das Strukt BAUM in der
Function_CRC byteweise für eine CRC-Berechnung  benutzen muss ?
Ich habe schon etliche Pointervariantetn für
*(&baumvariable+i)ausprobiert.
Vielen Dank im vorraus.
Gruss Max

von Rainer (Gast)


Lesenswert?

Hallo Max!

So wie ich das sehe, brauchst Du bei der Funktion "Function_CRC"
einen Zeiger auf die Struktur BAUM.

unsigned long int Function_CRC(BAUM *baumvariable);

Danach kannst Du mit dem Pointer arbeiten. Noch einfacher wäre es, wenn
Du Dir eine allgemeine Funktion erstellst, die Dir beginnend bei einem
Zeiger für eine gewisse Länge ausgehend von einem CRC-Startwert die
Summe erzeugt.

unsigned long int Function_GenericCRC(unsigned char *uc_data, unsigned
int i_length, unsigned long int ul_crc);

Dann kannst Du Deine Funktion "Function_CRC" umschreiben, dass sie
mit Deinen Bäumen zurechtkommt.

Viel Spaß damit!

von Max Jostkleigrewe (Gast)


Lesenswert?

Hallo Rainer,
vielen Dank für Deine schnelle Antwort.

Dein Hinweis für eine universelle Funktion, die den CRC für eine
variableLänge berechnet finde ich sehr gut.
(Ähnliche Ideen hatte ich auch schon.)

Meinst du damit, dass ich die Teile des Strukts einzeln berechnen muss
?

Also in etwa so ??
unsigned long int Function_GenericCRC(unsigned char *uc_data, unsigned
int i_length, unsigned long int ul_crc);

chk=0;
chk=CRC(Eiche.Ast1.Blatt,5,chk);
chk=CRC(Eiche.Ast1.Blattanzahl,2,chk);
chk=CRC(Eiche.Ast2,5,chk);
chk=CRC(Eiche.Astanzahl,5,chk);

.. und wenn ja, adressiere ich *uc_data wie folgt :?
for (i=0;i<i_length;i++){
....*(uc_data+i)....//soll inhalt von uc_data an position i sein
}

nochmals vielen Dank.

Max

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du musst nicht die Teile der struct einzeln berechnen, sondern
die Bytes der struct.  Eine CRC wird über einen Bytestrom
ermittelt.  Damit hilft auch kein Zeiger auf die struct selbst,
sondern nur ein Zeiger auf uint8_t (in einen solchen musst du
die Adresse der struct beim Aufruf wandeln).

CRC-Funktionen gibt's übrigens in der avr-libc (falls du einen
AVR nimmst -- du schreibst nichts dazu).

Eine CRC über eine struct ist u. U. etwas widersinnig, da du
damit auch das Padding zwischen den Elementen der struct mit
der CRC mit absicherst.  Weiß nicht, ob das wirklich das ist,
was du willst.  Ist für den AVR kein Thema (der hat kein
Padding), aber für andere Prozessoren schon.

Normalerweise appliziert man eine CRC nur auf externe
Kommunikation, nicht auf irgendwelche internen Daten -- und
dort ergibt sich der Bytestrom (octet stream) dann in der
Regel von selbst.

von Max Jostkleigrewe (Gast)


Lesenswert?

Hallo Jörg,
Danke für die Antwort.

der Prozessor ist ein i386 kompatibler amd Prozessor (in einem PanelPc)
Der Compiler ist GCC. (2.95)

Ich muss meinen Speicher während des Betriebs überwachen um
EMV-Störungen und ähnliche Fehlerquellen auschliessen zu können, die
theoretisch auftrete könnten.

Das heisst ich muss Checksummen über den flüchtigen Speicher und noch
über weitere Speicherbereiche bilden (Flashkarte....Adressleitungstest
und so weiter.. viel viel überprüfen)

Ich weiss auch, dass ein CRC Byteweise generiert wird.
Wenn ich aber ein Strukt habe, das komplizierter ist als in meinem
meinem Beispiel, welches aus sehr vielen verschiedenen Datentypen
(ulint,usint,char[],*char) besteht, habe ich ein Problem mit der
Adressierung der einzelnen Bytes in meinem Speicher.

Das CRC über den flüchtigen Speicher ist nur während der Laufzeit
nötig. Nach einem Neustart wird alles wieder neu berechnet. (Ausser auf
der Flashkarte);

Danke nochmal

Gruss Max

von Hans (Gast)


Lesenswert?

das padding problem sollte sich doch mit einem einfachen #pragma pack(1)
erledigen lassen oder???
zumindest hauts am arm mit dem gcc hin und der compiler vom VStudio6
tuts auch ;)

auf jedenfall darf das ganze dann ca so ausschaun:
1
//im header...
2
#pragma pack(1)
3
int crc_function(char *pData, int nLen);
4
5
//in der .c
6
int crc_function(char *pData, int nLen) {
7
  int i;
8
  for (i=0;i<nLen;i++) {
9
    //dein crc-code
10
  }
11
  return nCRC
12
}
13
14
//irgendwo im code...
15
BAUM sBaum;
16
int crc_value=crc_function((char *)&sBaum,sizeof(BAUM));

das sollte eigentlich hinhaun ..

73

von Max Jostkleigrewe (Gast)


Lesenswert?

Hans....
super vielen Dank !

der Cast auf den Charpointer hat mir gefehlt .
Ich habe immer auf char gecastet :-)

naja nochmal an alle vielen Dank für die schnelle und prompte Hilfe.
Bis zum nächsten mal
Max

Damit würde ich den Thread schliessen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Solange es nur darauf ankommt, den von den Daten benutzten
Speicher auf Veränderungen hin zu überwachen, kann einem ja
auch das Padding egal sein: man überwacht eben die Padding-Bytes
mit, egal was da gerade drin steht.

> Wenn ich aber ein Strukt habe, das komplizierter ist als in meinem
> meinem Beispiel, welches aus sehr vielen verschiedenen Datentypen
> (ulint,usint,char[],*char) besteht, habe ich ein Problem mit der
> Adressierung der einzelnen Bytes in meinem Speicher.

Nein, du hast das Prinzip einfach noch nicht verstanden: du willst
immer noch die CRC für jedes struct tag einzeln berechnen.  Das
ist Quatsch.  Du berechnest die CRC über den gesamten von der
struct belegten Speicher, ohne Rücksicht auf die Details.  Hans
hat das ja schon angedeutet, das mit dem #pragma pack() kannst du
weglassen.  (Der GCC nimmt sowieso keine Pragmas, bei ihm wäre
das ein __attribute__((packed)).)

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.