Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » memmove klappt irgendwie nicht

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
30.09.2004, 23:28 Uhr
Pablo
Supertux
(Operator)


Hi

ich hab folgendes:


C++:
int copy(CLAUSE* dest, const CLAUSE* src)
{

    LITERAL* literal;
    size_t len;
    size_t mem;

    if(!dest || dest->literals || !src || !src->literals) return 0;

    len = litlen(src->literals);
    mem = sizeof(LITERAL)*len+sizeof(LITERAL);

    printf("mem=%d\n", mem);

    literal = malloc(mem);

    if(!literal) return 0;

    literal=memmove(literal,src->literals, mem);

    if(!literal) return 0;

    dest->literals=literal;

    return 1;
}


wobei LITERAL und CLAUSE so aussehen:


C++:
#define LITERAL int

typedef struct S_CLAUSE
{
    LITERAL* literals;
} CLAUSE;



Ich bekomme eine Variable von Typ int*, die Member in src ist. src->literals enthält eine Reihe von Zahlen 2,3,1,3,0, die immer mit einer 0 enden. Die Funktion litlen liefert die Anzahl der Objekte in src->literals ohne die 0 gezählt zu haben, d.h. litlen(2,3,1,3,0)=4.

Ich den kompletten Inhalt kopieren, deshalb definiere ich LITERAL* literal; und berechne den Platz den ich brauche, das wäre nämlich sizeof(LITERAL)*len+sizeof(LITERAL); weil ich die 0 auch kopieren will. Oder hab ich da einen Denkfehler?

Wenn ich beide Reihen auf dem Monitor ausgebe, bekomme ich für folgendes:
{2, 22, 18, -23, 21, -31, -254, 54, 354, -454}
Wenn ich die kopierte Reihe ausgebe, bekomme ich aber:
{2, 22, 18, -23, 21, 49, -254, 54, 354, -454}
mem ist in diesem Beispiel 44, also 11*sizeof(LITERAL), hab das erwartet.

wieso hat sich die -31 in 49 verwandelt? Wo hab ich nen Fehler gemacht?

Das komische ist, wenn ich die erste Reihe nochmal ausgeben, (nach dem ich copy aufgerufen habe) bekomme ich
{2, 22, 18, -23, 21, 49, 2, 22, 18, -23, 21, 49, -254, 54, 354, -454}
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 30.09.2004 um 23:35 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
30.09.2004, 23:50 Uhr
virtual
Sexiest Bit alive
(Operator)


Also zunächst mal ist zu sagen, daß memmove an dieser Stelle nicht notwenig ist: memmove ist eigentlich nur dann interessant, wenn sich zeil und quellbereich überschneiden, was hier aber nie der Fall sein kann. Ic h würde also memcpy nehmen. Das ist performanter, weil es weniger tests machen muß.

Unter der Annahme, daß litlen korrekt ist, hat die Routine keine Fehler, die ich sehen würde.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
30.09.2004, 23:54 Uhr
Pablo
Supertux
(Operator)


Ich hab memcpy benutzt und hab genau den selben Fehler gehabt. Da aber in den man pages stand, dass die Bereiche sich nicht überschneiden sollen, hab ich mich für memmove entschieden, hat aber nix gebracht.

Nun ja, so sieht meine litlen aus:


C++:
size_t litlen(const LITERAL* literal)
{
    size_t len=0;
    if(!literal) return 0;
    while(*literal++&&++len);
    return len;
}



An der Stelle muss ich sagen, dass LITERAL* sich wie char* verhält, und das 0 ist das Ende.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.09.2004, 23:59 Uhr
virtual
Sexiest Bit alive
(Operator)


Da du ja Linux benutzt, empfehle ich Dir einfach mal, daß Programm mit valgrind zu starten... Das sollte zeigen, wo du den Fehler hast...
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
01.10.2004, 00:25 Uhr
Pablo
Supertux
(Operator)


ich schau mal nach, ich muss es aber zuerst installieren

edit: Also muss zugeben, dass das Programm alles anzeigt, aber irgendwie hilft mir das nicht weiter.

Ich bekomme sowas


Code:
==16654== Invalid read of size 4
==16654==    at 0x8048690: searchLiteral (in /home/rex/projects/fsat/fsat-0.0.1/src/fsat)
==16654==    by 0x80485D9: insertLiteral (in /home/rex/projects/fsat/fsat-0.0.1/src/fsat)
==16654==    by 0x80484EA: main (in /home/rex/projects/fsat/fsat-0.0.1/src/fsat)
==16654==    by 0x4025885B: __libc_start_main (in /lib/libc-2.3.3.so)
==16654==    Address 0x41071090 is 0 bytes after a block of size 4 alloc'd
==16654==    at 0x40025BBE: malloc (vg_replace_malloc.c:153)
==16654==    by 0x8048654: insertLiteral (in /home/rex/projects/fsat/fsat-0.0.1/src/fsat)
==16654==    by 0x80484E0: main (in /home/rex/projects/fsat/fsat-0.0.1/src/fsat)
==16654==    by 0x4025885B: __libc_start_main (in /lib/libc-2.3.3.so)



==16654== Invalid read of size 4? Was bedeutet das?

also, ich hab schon einen Fehler gefunden, aber in einer anderen Datei.

C++:
tmp = realloc(tmp, len+sizeof(LITERAL));



da hab ich nur len und nicht (len+1)*sizeof(LITERAL)
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 01.10.2004 um 01:03 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
01.10.2004, 01:08 Uhr
Pablo
Supertux
(Operator)


geil..... valgrind ist echt ein genialies Programm, das erste Mal hatte ich 107 Fehler, jetzt hab ich geschafft, dass 0 Fehler angezeigt werden, und das Programm läuft, wie es laufen soll. Es ist unglaublich, wie schnell man Fehler mit malloc/realloc machen kann, ohne zu merken. Danke für den Tipp.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 01.10.2004 um 02:09 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
01.10.2004, 10:32 Uhr
ao

(Operator)



Zitat von Pablo:
geil..... valgrind ist echt ein genialies Programm, das erste Mal hatte ich 107 Fehler, jetzt hab ich geschafft, dass 0 Fehler angezeigt werden, und das Programm läuft, wie es laufen soll. Es ist unglaublich, wie schnell man Fehler mit malloc/realloc machen kann, ohne zu merken. Danke für den Tipp.

Dann lass mich armen Windows-Tropf mal nicht ganz so dumm sterben und sag, wo der Fehler in der litlen-Funktion war, ich hab nämlich grad keine Zeit, selber zu suchen, aber interessieren täts mich schon.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
01.10.2004, 14:07 Uhr
Pablo
Supertux
(Operator)


Nein, es war nicht litlen. Ich hab ein Paar Funktionen geschrieben, die die Literalen hinzufügen, ohne dass ich mich um die Speicherverwltung kümmern muss, dafür muss sich int insertLiteral darum kümmern. Ich hab so gemacht, wenn ein CLAUSE Objekt erstellt wird, dann zeigt literals auf NULL und wenn man da ein Literal hinzugefügen will, muss mit malloc Speicher für 2 Einträge reserviert werden und in literals[0] den Wert des Literals und in literals[1] muss 0 stehen. Ich hab aber Speicher für einen einzigen Eintrag reserviert.

Wenn literals schon Elemente hat, und insertLiteral aufgeruft wird, dann muss man mit realloc literals um eins erhöhen und hab realloc so benutzt

C++:
tmp = realloc(tmp, len+sizeof(LITERAL));



und das ist falsch, weil len nur die Anzahl der Elemente enthält und außerdem sollte len+1 sein und noch dazu "mal" sizeof(LITERAL), damit die Anzahl in Bytes kommt. Das waren im Grunde die 2 dummste Fehler, dann merkete ich dass in anderen Funktionen ein bisschen schlmmpig war, weil ich nicht vorher überprüft habe, dass literals nicht NULL sein soll.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 01.10.2004 um 14:11 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
01.10.2004, 14:19 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von Pablo:


C++:
tmp = realloc(tmp, len+sizeof(LITERAL));




Daß das noch immer falsch sein kann, ist dier hoffentlich klar? Beachte diesen feinen aber kleinen Unterschied:

C++:
typedef struct {
    void* data;
    size_t len;
} data_t;


int enlarge_falsch(data_t* d, size_t newlen) {
     d->data = realloc(d->data, newlen);
     return d->data!=NULL;
}

int enlarge_okay(data_t* d, size_t newlen) {
     void* p = realloc(d->data, newlen);
     if (!p) return 0;
     d->data = p;
     return 1;
}


Wenn es Dir nicht klar sein sollte: die falsche Version produziert ein Speicherloch, die letztere nicht. Das gilt für genau den Fall, daß das realloc schiefgeht.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
01.10.2004, 14:40 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


rofl ich wusste das virtual gleich ein anfall bekommt wenn er das mit dem realloc sieht

was dem pablo sein "int main" dem virtual das "realloc"
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: