Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Problem mit realloc

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
13.09.2005, 18:33 Uhr
netdisaster



Ich habe ein Problem mit der realloc-Funktion:

Ich stelle einen Speicherbereich mit calloc zur Verfügung für eine struct-Matrix.
Es sollen also in z.B. 10 Zeilen jeweils 5-mal eine Struktur gespeichert werden.
Sicherheitshalber stelle ich Speicherplatz für 15 Zeilen zur Verfügung.

Innerhalb einer Funktion stelle ich nun fest, dass ich mehr als nur 10 Zeilen brauche und erhöhe den Speicherbereich mit realloc um weitere 10 Zeilen incl. Sicherheit, also so, dass ich danach 25 Zeilen speichern könnte.
(Über diese 5 Sicherheitszeilen kann man sich jetzt wundern oder nicht. Ich jedenfalls hab aufgehört, mich beim Programmieren über irgendwas zu wundern ...)

Ich weiß, dass ich Zugriff auf diesen neuen Speicher für die 25 Zeilen habe, das habe ich ausprobiert. Sowohl direkt nach dem realloc als auch außerhalb der Funktion, in der das realloc steht. Die Adressenweitergabe an main und andere Funktionen scheint also zu funktionieren.
Allerdings schreibt mir mein Programm trotzdem nur Daten in die ersten ursprünglich bereitgestellten 15 Zeilen und steigt dann aus unerfindlichen Gründen aus.

Insgesamt brauche ich 81 Zeilen, in die was geschrieben werden soll. Wenn ich nun am Anfang für 90 Zeilen Platz reserviere läuft mein Programm problemlos. Nur wenn ich die realloc-Funktion nutze, kommt eine System-Fehlermeldung in der Art:
"Wenden Sie sich an den Hersteller, falls das Problem weiterhin besteht."
Mit den Details dazu kann ich natürlich überhaupt nichts anfangen.

Leider hat mein Programm aktuell etwa 1600 Zeilen.
Ich weiß nicht, wie ich das so sinnvoll kürzen kann, dass ich es hier vernünftig posten könnte. Am liebsten würde ich es also jemandem zuschicken.

Also falls mir irgendwer 1. Hilfe leisten könnte ...
dann vielen Dank dafür!

Grüße,
netdisaster
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
13.09.2005, 18:52 Uhr
imhotep
followed the white rabbit


Du könntest zumindest deine calloc und realloc Aufrufe posten. Vielleicht machst du Fehler beim neuberechnen oder beim Übergeben zwischen den einzelnen Funktionen.


C++:
//anfang
char ** matrix = (char**) calloc(15, sizeof(char*));
for (int i = 0; i < 15; i++) matrix[i] = (char*) calloc(100, sizeof(char));

//realloc
matrix = (char**) realloc(matrix, 25 * sizeof(char*));
for (int i = 15; i < 25; i++) matrix[i] = (char*) calloc(100, sizeof(char));

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
13.09.2005, 19:04 Uhr
netdisaster



gut, ich versuch*s mal, die wichtigsten Sachen hier rein zu bringen.
kleinen Moment Geduld ...

netdisaster
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
13.09.2005, 19:22 Uhr
netdisaster




C++:
#define PARTS 5
#define MEM_UP 120

typedef struct {int BTL_Nr, CAD_Nr; char BTL_Partname[NAMELEN]; int BTL_Art;
                float BTL_Weight; ROTATION BTL_Rot;} BAUTEIL;
typedef struct {int TBG_Nr, TBG_Pcount; BAUTEIL *TBG_Part[PARTS+1]; float TBG_Weight;} STABTBG;
typedef struct {int OP_Nr; STABTBG *OP_j, *OP_i, *TBG_Nr;} OPERATION;
typedef OPERATION MONTAGEFOLGE[PARTS];

void cr_newMONT(int, int, int, int *, int *, int *, int *,
                STABTBG *, OPERATION *, BAUTEIL *,
                MATRIX_ID mat_id[][PARTS+1], MONTAGEFOLGE *MONT_List);
void poco_mont(int, int *, int *, int *, int, int, int *, STABTBG *, OPERATION *,
               MONTAGEFOLGE *, BAUTEIL *, MATRIX_ID mat_id[][PARTS+1],
               int MAN_potential[], int instabil[][6],
               int mat_separation[][PARTS+1][PARTS+1][6],
               int mat_manipulation[][PARTS+1][PARTS+1][6],
               float mat_stability[][PARTS+1][PARTS+1],
               int mat_GEOdfk[][PARTS+1][PARTS+1],
               int mat_MECdfk[][PARTS+1][PARTS+1],
               int mat_DFK[][PARTS+1][PARTS+1]);

int main()
{
   int montcount=1;
   int maxmont=MEM_UP;

   MONTAGEFOLGE *MONT_List;
   MONT_List=(MONTAGEFOLGE *) calloc(maxmont+5, sizeof(MONTAGEFOLGE));
   if (MONT_List==NULL) {
      fprintf(stderr, "Speicher-ERROR: MONT_List zu gross");
      exit(1);
   }
  
   [...]
  
   poco_mont(step, &tbgcount, &opcount, &montcount, maxtbg, maxop, &maxmont,
             TBG_List, OP_List, MONT_List, partlist,
             mat_id, MAN_potential, instabil,
             mat_separation, mat_manipulation, mat_stability,
             mat_GEOdfk, mat_MECdfk, mat_DFK);
  
}

void poco_mont(int step, int *tbgcount, int *opcount, int *montcount,
               int maxtbg, int maxop, int *maxmont,
               STABTBG *TBG_List, OPERATION *OP_List, MONTAGEFOLGE *MONT_List,
               BAUTEIL *partlist, MATRIX_ID mat_id[][PARTS+1],
               int MAN_potential[],
               int instabil[][6],
               int mat_separation[][PARTS+1][PARTS+1][6],
               int mat_manipulation[][PARTS+1][PARTS+1][6],
               float mat_stability[][PARTS+1][PARTS+1],
               int mat_GEOdfk[][PARTS+1][PARTS+1],
               int mat_MECdfk[][PARTS+1][PARTS+1],
               int mat_DFK[][PARTS+1][PARTS+1])
{
   cr_newMONT(step, line, col, tbgcount, opcount, montcount, maxmont,
              TBG_List, OP_List, partlist, mat_id, MONT_List);  
   poco_mont(step, tbgcount, opcount, montcount, maxtbg, maxop, maxmont,
             TBG_List, OP_List, MONT_List, partlist,
             mat_id, MAN_potential, instabil,
             mat_separation, mat_manipulation, mat_stability,
             mat_GEOdfk, mat_MECdfk, mat_DFK);
}

void cr_newMONT(int step, int line, int col,
                int *tbgcount, int *opcount, int *montcount, int *maxmont,
                STABTBG *TBG_List, OPERATION *OP_List, BAUTEIL *partlist,
                MATRIX_ID mat_id[][PARTS+1], MONTAGEFOLGE *MONT_List)
{
   MONTAGEFOLGE *MONT_List_alt;

   [...]

// Schritt 6:
// Prüfen, ob gefundene Montagefolge komplett
// und falls ja, montcount erhöhen
   if (step==PARTS-1) {      
      ++(*montcount);
      // bei Bedarf mehr Speicher bereitstellen
      if (*montcount==*maxmont) {
         MONT_List_alt=MONT_List;
         *maxmont += MEM_UP;
         MONT_List=(MONTAGEFOLGE *) realloc(MONT_List_alt, (*maxmont+5)*sizeof(MONTAGEFOLGE));
         for (montc=(*maxmont-MEM_UP); montc<(*maxmont+5); montc++) {
            for (fstep=0; fstep<PARTS; fstep++) {
               MONT_List[montc][fstep].OP_Nr=0;
               MONT_List[montc][fstep].OP_i=NULL;
               MONT_List[montc][fstep].OP_j=NULL;
               MONT_List[montc][fstep].TBG_Nr=NULL;
            }
         }
         if (MONT_List == NULL) {
            fprintf(stderr, "\n\nSpeicher-ERROR: MONT_List zu gross");
            MONT_List=MONT_List_alt;
         }
      }
   }
}



Ist jetzt eben stark aus dem Zusammenhang. Ich hoffe, es ist dennoch verständlich ...

netdisaster

Dieser Post wurde am 13.09.2005 um 19:27 Uhr von netdisaster editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
13.09.2005, 19:47 Uhr
Pablo
Supertux
(Operator)



Zitat von imhotep:
Du könntest zumindest deine calloc und realloc Aufrufe posten. Vielleicht machst du Fehler beim neuberechnen oder beim Übergeben zwischen den einzelnen Funktionen.


C++:
//anfang
char ** matrix = (char**) calloc(15, sizeof(char*));
for (int i = 0; i < 15; i++) matrix[i] = (char*) calloc(100, sizeof(char));

//realloc
matrix = (char**) realloc(matrix, 25 * sizeof(char*));
for (int i = 15; i < 25; i++) matrix[i] = (char*) calloc(100, sizeof(char));





realloc falsch benutzt! Schon mal dran gedacht, was passiert, wenn realloc NULL zurückliefert?


C++:
//anfang
char ** matrix = (char**) calloc(15, sizeof(char*));
char** tmp;

// immer überprüfen, dass es kein NULL ist!

if(!matrix)
{
    // Fehlerbehandlung und beenden
}

for (int i = 0; i < 15; i++) matrix[i] = (char*) calloc(100, sizeof(char));

//realloc
tmp = (char**) realloc(matrix, 25 * sizeof(char*));

if(!tmp)
{
    // Fehlerbehandlung. Speicher konnte nicht vergrössert werden
    // routine abbrechen
}

if(tmp != matrix)
    matrix = tmp;

for (int i = 15; i < 25; i++) matrix[i] = (char*) calloc(100, sizeof(char));


--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 13.09.2005 um 19:48 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
13.09.2005, 21:37 Uhr
netdisaster



Die Fehlerbehandlung für Rückgabewert NULL bei realloc ist aber bei mir jetzt nicht wirklich das Problem, da ich ja auf den von realloc reservierten größeren Speicherbereich zugreifen kann. Zumindest händisch, also per von Hand zusätzlich geschriebener Test-Zuweisungen, lassen sich Werte in die 25 Zeilen eintragen, auch in jede Spalte. Nach dem realloc hab ich also eindeutig 25 Zeilen zur Verfügung. Dennoch schreibt mir das Programm nur in die ersten 15 Zeilen, die ich durch calloc bereitgestellt habe.

Ich probier jetzt mal noch, was passiert, wenn ich statt calloc malloc verwende. Das Ergebnis poste ich dann. Kann mir aber nicht vorstellen, dass 0-Initialisierung des Speichers durch calloc entscheidenden Einfluss hat. Andererseits: ich hab aufgehört mich zu wundern ...

netdisaster
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
13.09.2005, 22:09 Uhr
FloSoft
Medialer Over-Flow
(Administrator)



Zitat von MSDN:

realloc returns a void pointer to the reallocated (and possibly moved) memory block. The return value is NULL if the size is zero and the buffer argument is not NULL, or if there is not enough available memory to expand the block to the given size. In the first case, the original block is freed. In the second, the original block is unchanged. The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.



Aus dem Grund prüfen ob != NULL, erstens kanns sonst böse av's geben zumindest aber speicherlöcher.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
13.09.2005, 22:16 Uhr
Pablo
Supertux
(Operator)



Zitat von netdisaster:
Die Fehlerbehandlung für Rückgabewert NULL bei realloc ist aber bei mir jetzt nicht wirklich das Problem, da ich ja auf den von realloc reservierten größeren Speicherbereich zugreifen kann. Zumindest händisch, also per von Hand zusätzlich geschriebener Test-Zuweisungen, lassen sich Werte in die 25 Zeilen eintragen, auch in jede Spalte. Nach dem realloc hab ich also eindeutig 25 Zeilen zur Verfügung. Dennoch schreibt mir das Programm nur in die ersten 15 Zeilen, die ich durch calloc bereitgestellt habe.


Mein Post war auch nicht bezogen auf dein Problem, sondern auf die falsche Benutzung von realloc. Mag sein, dass bei so wenig allokierten Speicher, realloc kein NULL zurückliefert, aber das ist häufig eine Quelle von Problemen. Wenn du viel Speicherreservierungen mit realloc machst, kann schon passieren, dass realloc NULL zurückgibt und dann hast du den Speicherverloren.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
14.09.2005, 13:03 Uhr
netdisaster



Die Start-Initialisierung des Speicherbereichs mit malloc anstelle von calloc hat das Problem nicht verändert. Die automatische Null-Setzung des Speicherbereichs, die von realloc leider ja nicht gemacht wird, ist also auch nicht das Problem. Dachte schon, vielleicht hab ich irgendwo eine Abfrage, ob irgendwas 0 oder NULL ist. Ist aber nicht so ...
Da ich anfänglich mehr Speicher zur Verfügung stelle als ich als Obergrenze, bei der ich neuen Speicher anfordere, festgelegt habe, kann also auch die Umadressierung (die wird tatsächlich gemacht, das wurde abgefragt) nicht schuld sein.

Ich fasse zusammen:
- der anfänglich mit malloc oder calloc reservierte Speicher ist vorhanden.
- nachträglich mit realloc reservierter Speicher ist ebenso vorhanden. Der Zugriff auf den Speicherbereich wurde händisch getestet.
- dennoch schreibt mein Programm nur in den anfänglich von malloc/calloc bereitgestellten Speicher und bricht dann bei Zugriff auf den erweiterten Speicher ab.

Ich bin echt ratlos ...

netdisaster
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
14.09.2005, 13:11 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von netdisaster:

Ich fasse zusammen:
- der anfänglich mit malloc oder calloc reservierte Speicher ist vorhanden.
- nachträglich mit realloc reservierter Speicher ist ebenso vorhanden. Der Zugriff auf den Speicherbereich wurde händisch getestet.
- dennoch schreibt mein Programm nur in den anfänglich von malloc/calloc bereitgestellten Speicher und bricht dann bei Zugriff auf den erweiterten Speicher ab.

Ich bin echt ratlos ...

netdisaster


Du übergibst Der Funktion cr_newMONT den Pointer auf den Speicherbereich als Wert, nicht als referenz. daher bekommt niemand mit, wenn realloc den Speicherblock in folge einer Speichervergrößerung verändert hat. Vereinfacht kann man Dein Problem so zusammenfassen:

C++:
int main() {
   void* ptr = malloc(...);
   function_die_ptr_veraendert(...., ptr, ...);

}
void   function_die_ptr_veraendert(...., void* ptr, ...) {
   ptr = NULL/realloc(...);
}


In main wird die Änderung nie sichtbar. Da musst Du schon machen:

C++:
int main() {
   void* ptr = malloc(...);
   function_die_ptr_veraendert(...., &ptr, ...);

}
void   function_die_ptr_veraendert(...., void** ptr, ...) {
   *ptr = NULL/realloc(...);
}


Oder in C++:

C++:
int main() {
   void* ptr = malloc(...);
   function_die_ptr_veraendert(...., ptr, ...);

}
void   function_die_ptr_veraendert(...., void*& ptr, ...) {
   ptr = NULL/realloc(...);
}


--
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
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: