2016-03-30 8 views
1

ich eine generische quicksort zu schreiben versuche:Was ist los mit meiner generischen schnellen Sortierung?

void _qsort(void *ptr, 
     size_t lrange, 
     size_t rrange, 
     size_t size, 
     int (*cmp)(const void *, const void *)) 
{ 
    if (lrange < rrange) { 
     size_t i, j; 
     void *key; 

     key = malloc(size); 
     i = lrange; 
     j = rrange; 
     memcpy(key, ptr + i * size, size); 
     while (i < j) { 
      while (i < j && (*cmp)(ptr + j * size, key) > 0) 
       j--; 
      if (i < j) { 
       memcpy(ptr + i * size, ptr + j * size, size); 
       i++; 
      } 
      while (i < j && (*cmp)(key, ptr + i * size) > 0) 
       i++; 
      if (i < j) { 
       memcpy(ptr + j * size, ptr + i * size, size); 
       j--; 
      } 
     } 
     memcpy(ptr + i * size, key, size); 
     _qsort(ptr, lrange, i - 1, size, cmp); 
     _qsort(ptr, i + 1, rrange, size, cmp); 
    } 
} 

ich einen einfachen Test auf einem int-Array schreiben, ist dies die cmp funciton:

int cmp(const void *x, const void *y) 
{ 
    return *(int *)x - *(int *)y; 
} 

Es einen Core Dump verursachen, aber wenn ich Ändern Sie den Typ von lrange, rrange, i, j von size_t bis int, es läuft richtig, ich kann nicht verstehen, warum?

+1

Schauen Sie sich [diese Frage] an (http://stackoverflow.com/questions/2550774/what-is-size-t-in-c), um besser zu verstehen, was 'size_t' ist und warum es einen Absturz verursacht. TIPP: Es liegt wahrscheinlich daran, dass memcpy damit arbeitet. aber du bist nah dran. – Shark

+0

Warum debuggen Sie nicht den Core Dump? – kamikaze

+0

Es gibt ein Problem, wenn ich diesen Core-Dump debuggen, "malloc.c: Keine solche Datei oder Verzeichnis." – protream

Antwort

2
size_t i, j; 

sind vorzeichenlose Typen. Wenn ein Wert einer vorzeichenlosen Variablen 0 ist und 1 subtrahiert wird, wird der Wert auf den größtmöglichen Wert für diesen vorzeichenlosen Typ umgebrochen.

Diese auf den Leitungen passieren können:

j--; 

und:

_qsort(ptr, lrange, i - 1, size, cmp); 

Wenn der ungültige Wert als Index für ein Array verwendet wird, wird es einen Segmentation Fault, da das Programm verursachen kann nicht lesen eine Adresse, die außerhalb der Grenzen liegt.


Sie Namen nicht mit dem Präfix verwenden _, _qsort, wie die für die Implementierung reserviert ist.

+0

Ich denke, ich habe den Punkt bekommen. Aber wie kann ich meinen Code ändern? – protream

+0

@protream Stellen Sie sicher, dass Sie niemals einen Wert umbrechen oder signierte Typen verwenden. (Vergessen Sie nicht, diese Funktionen umzubenennen.) – 2501

+0

@protream Das wird in der Antwort erklärt. – 2501

3
memcpy(key, ptr + i * size, size); 

ptr ist ein void *, können Sie keine Pointer-Arithmetik mit void * verwenden, wechseln Sie zu char * (als qsort in der Standardbibliothek).

+2

Schön entdeckt. Um dies zu vermeiden, verwenden Sie einen standardkonformen Compiler. Zum Beispiel 'gcc -std = c11 -pedantic-Fehler // gibt ausgezeichnete C-Compiler' anstatt 'gcc // gibt Nicht-Standard-crapiler – Lundin