2016-07-13 11 views
1

Hier ist der Code in Frage, es ist eine Funktion, die einen int-Array reallocs und fügt eine Zahl am Ende davonWarum gibt mir diese Realloc-Instanz SIGABRT?

int *add_to_array(int *arr, unsigned int num, int newval) 
{ 
    if(arr != NULL){ 

     int *newarr = realloc(arr, sizeof(int) * (num+1)); 
      if(!newarr){ 
       free(arr); 

      }else{ 
       free(newarr); 
      } 
      arr[num] = newval; 
      return arr; 
    } 
    else{ 

    return NULL; 

    } 

} 

Problem ist, wenn ich diese Funktion einmal anrufen, es funktioniert gut, aber wenn ich nennen es ein zweites Mal, der Debugger gibt mir eine SIGABRT an der Linie

int *newarr = realloc(arr, sizeof(int) * (num+1)); 

Hier ist, wie ich die Funktion

Aufruf bin
array = add_to_array(array, 5, 10); 
array = add_to_array(array, 6, 100); 

EDIT: habe ich es geschafft zu s Ølve dies mit diesem neuen Code

int *add_to_array(int *arr, unsigned int num, int newval) 
{ 
if(arr != NULL){ 

int *newarr =realloc(arr, sizeof(int) * (num+1)); 
if(!newarr){ 
    return NULL; 
}else{ 
newarr[num] = newval; 
return newarr; 
} 
} 
else{ 

    return NULL; 

} 

} 

Noch eine Frage, für den Fall, wobei realloc den gegebenen Zeiger arr realloc ausfällt, tut arr in diesem Fall null wird oder ist es immer noch gültig?

+4

Sie reservieren also ein neues Array (das alte Array wird dabei freigegeben), dann geben Sie das neue Array frei und schreiben dann Daten in das alte Array, das jetzt freigegeben wird? – immibis

+0

Wenn die Zuweisung fehlschlägt, geben Sie den Speicher frei, auf den der Zeiger auf das ursprüngliche Array zeigt. Wenn dies gelingt, geben Sie den Speicherplatz frei, den Sie erfolgreich zugewiesen haben, und schreiben Sie ihn? – user3078414

+1

'if (! Newarr) { frei (arr); zurück NULL; } sonst { arr = newarr } ' – BLUEPIXY

Antwort

1

Wenn realloc versagt Sie wahrscheinlich das alte Array speichern wollen und nichts zu tun, so:

 if(!newarr){ 
      free(arr); 

werden sollten:

 if(!newarr){ 
      return NULL // Allocation fails, the old array saved. Check the return value outside the function 
     } 

Wenn realloc erfolgreich zu sein, Sie sicher nicht wollen, kostenlos das neue Array, aktualisieren sie nur den letzten Wert darin, so:

 }else{ 
      free(newarr); 
     } 
     arr[num] = newval; 
     return arr; 

werden sollten:

 newarr[num] = newval; 
     return newarr; 
+0

@BLUEPIXY Sie richtig, nur sah, dass und beheben –

+0

Wenn Realloc fehlschlägt dann sollte der alte Speicher manuell befreit werden Zu diesem Zeitpunkt kann der PGM nicht fortgesetzt werden und sollte abgebrochen werden. – sjsam

+0

@sjsam Warum die alten Speicher freigeben und die Daten verlieren? Vielleicht möchte er es speichern oder eine andere Sache tun –

2

nicht nur nicht

else{ 
      free(newarr); 
     } 

Sinn machen, sondern auch trotzt sie den Zweck der

int *newarr = realloc(arr, sizeof(int) * (num+1)); 

Wenn realloc erfolgreich ist, arr=newarr zu tun.


Referenz

[ realloc ] Referenz sagt:

auf Erfolg, den Zeiger auf den Anfang des neu zugewiesenen Speicher zurückgibt. Der zurückgegebene Zeiger muss mit free() oder realloc() freigegeben werden. Der ursprüngliche Zeiger ptr ist ungültig und jeder Zugriff auf ist ein undefiniertes Verhalten (auch wenn die Neuzuordnung in-Place erfolgte).

Bei einem Fehler wird ein Nullzeiger zurückgegeben. Der ursprüngliche Zeiger ptr bleibt gültig und muss möglicherweise mit free() oder realloc() freigegeben werden.

+2

Ihr letzter Satz ist falsch - die von 'realloc()' zurückgegebene Adresse ist nicht immer die übergebene Adresse, auch wenn die Zuweisung erfolgreich ist. Mit anderen Worten, 'realloc()' kann die Daten verschieben. –

+0

@ JonathanLeffler: Gültiger Punkt, und "chance of moving" ist der Grund, warum wir einen neuen Zeiger 'newarr' verwendet haben. Thankyou;) – sjsam

+0

Es ist wahrscheinlich passiert es nicht Realität, aber Sie beheben nicht den Code für den Fall Realloc schlägt fehl –

1

Ihr Code führt zu undefiniertem Verhalten, wenn Sie nach der Neuzuweisung versuchen, in den ursprünglichen Block zu schreiben. Wenn die Neuzuweisung fehlschlägt - Sie befreien diesen Block manuell, bevor Sie ihn schreiben. In anderen Fällen dürfen Sie diesen Block nicht berühren, da realloc() einen neuen zurückgegeben hat und der ursprüngliche eine Schacht intern freigegeben wurde.Und SIGABRT - ist eine implementierungsspezifische Benachrichtigung über erkannte Heap-Beschädigung oder Missbrauch der malloc-family-API. Lesen Sie ungefähr realloc() sorgfältig.

Verwandte Themen