GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Unterschiedliche Deklarationen von qsort_r auf Mac und Linux

Wird es effektiv sein, sich irgendwo zu beschweren, um dieses Problem zu lösen?

Leider nein. Das ist schon zu lange so und es gibt zu viel Code, der sich darauf verlässt.

Ich denke, die zugrunde liegende Frage ist "warum treten diese Inkompatibilitäten auf "? Ich werde darauf antworten. Es scheint darauf hinauszulaufen, dass BSD es zuerst implementiert, aber mit einer schlechten Schnittstelle. ISO und später GNU haben die Schnittstelle repariert und entschieden, dass sich der Kompatibilitätsbruch gelohnt hat. Und Microsoft tut, worauf sie Lust haben." P>

Wie von @Downvoter (großartiger Name) hervorgehoben, qsort_r ist eine Nicht-Standard-Funktion. Es wäre schön, wenn es Standard wäre, aber darauf kann man sich nicht verlassen. qsort_s ist eine Art Standard in C11 Annex K, aber niemand implementiert C11 wirklich, geschweige denn seine Anhänge, und ob Annex K eine gute Idee ist, ist fraglich.

Wie bei vielen C- und Unix-Problemen läuft dies auf BSD vs. GNU vs. Microsoft und ihre Unfähigkeit, C-Erweiterungen zu koordinieren, hinaus. Linux ist GNU. OS X ist ein Mischmasch aus vielen Dingen, aber für C folgt es BSD.

FreeBSD hat qsort_r hinzugefügt im September 2002. Visual Studio 2005 enthielt einen etwas anderen qsort_s . ISO formalisierte noch einmal einen anderen qsort_s im Jahr 2007. Schließlich kamen GNUs Jahre später in glibc 2.8 im Jahr 2008, anscheinend nach ISO. Hier ist ein alter Thread aus den Jahren 2004 bis 2008, der qsort_r anfordert in glibc implementiert werden, was einige Gründe hat.

Zur Erinnerung:Hier ist qsort wie in C99 definiert.

void qsort(
    void *base, size_t nmemb, size_t size,
    int (*compar)(const void *, const void *)
);

FreeBSD war das erste im September 2002. Sie entschieden, dass qsort_r sollte den qsort brechen Schnittstelle und setzen Sie das "thunk"-Argument vor die Vergleichsfunktion.

void qsort_r(
    void *base, size_t nmemb, size_t size,
    void *thunk,
    int (*compar)(void *, const void *, const void *)
);

Wieso den? Sie müssen Garrett Wollman fragen, wer den Patch geschrieben hat. Wenn man sich den Patch ansieht, sieht man seine Änderungen an CMP Es wurde entschieden, dass es ein gutes Muster war, das "Thunk" zuerst zu haben. Vielleicht haben sie beschlossen, dass die Leute sich daran erinnern würden, dass "die Vergleichsfunktion am Ende bleibt". Leider bedeutet dies qsort und qsort_r Die Vergleichsfunktionen von haben ihre Argumente umgekehrt. Sehr verwirrend.

Inzwischen hat Microsoft, immer der Innovator, qsort_s in Visual Studio 2005.

void qsort_s(
   void *base, size_t num, size_t width,
   int (__cdecl *compare )(void *, const void *, const void *),
   void * context
);

"s" für "secure" statt "r" für "reentrant", das alle anderen möglicherweise gemäß einer ISO-Konvention (siehe unten) oder umgekehrt verwendet haben. Sie haben das "Thunk" an das Ende von qsort_s gesetzt , wobei die Argumente dieselben wie bei qsort bleiben , aber für maximale Verwirrung geht das "Thunk" am Anfang der Vergleichsfunktion wie BSD. Sie wählten die schlechtestmögliche Option.

Um die Sache noch schlimmer zu machen, veröffentlichte ISO 2007 TR 24731-1, um die Begrenzungsprüfung zur C-Standardbibliothek hinzuzufügen (danke @JonathanLeffler für den Hinweis). Und ja, sie haben ihren eigenen qsort_r , aber es heißt qsort_s ! Und ja, es ist anders als alle anderen!

errno_t qsort_s(
    void *base, rsize_t nmemb, rsize_t size,
    int (*compar)(const void *x, const void *y, void *context),
    void *context
);

Sie haben sich klugerweise entschieden, die Argumente bei qsort_s zu belassen und seine Vergleichsfunktion eine Obermenge von qsort wahrscheinlich argumentieren, dass es für die Leute einfacher wäre, sich zu erinnern. Und sie fügten einen Gegenwert hinzu, wahrscheinlich eine gute Idee. Um die Verwirrung noch zu verstärken, war dies damals ein "Technischer Bericht" und nicht Teil des C-Standards. Es ist jetzt "Annex K" des C11-Standards, immer noch optional, hat aber mehr Gewicht.

GNU entschied dasselbe, möglicherweise in Anlehnung an qsort_s von ISO .

void qsort_r(
    void *base, size_t nmemb, size_t size,
    int (*compar)(const void *, const void *, void *),
    void *arg
);

Betrachten Sie den glibc-Patch, der qsort_r hinzufügt es war wahrscheinlich auch einfacher zu implementieren. Um es genau zu wissen, müssen Sie Ulrich Drepper fragen.

BSDs Entscheidung, Argumente mit qsort auszutauschen und seine Vergleichsfunktion hat im Laufe der Jahre wahrscheinlich für viel Verwirrung und Fehler gesorgt. Die ISO / GNU-Entscheidung, sie gleich zu lassen, ist wohl besser. ISO entschied sich für einen anderen Namen. GNU hat beschlossen, die Kompatibilität mit der BSD-Funktion zu brechen. Microsoft beschloss, alles zu tun. Jetzt stecken wir mit vier inkompatiblen Implementierungen fest. Da die Vergleichsfunktionen unterschiedliche Signaturen haben, ist ein Kompatibilitätsmakro nicht trivial.

(Dies ist alles eine Rekonstruktion des Codes. Für ihre eigentlichen Begründungen müssen Sie die Mailinglisten-Archive durchsuchen.)

Ich kann GNU oder BSD oder ISO oder Microsoft nicht wirklich die Schuld geben ... ok, ich kann Microsoft dafür verantwortlich machen, absichtlich versucht zu haben, C zu töten schmerzhaft langsam und die Compiler-Autoren müssen manchmal tun, was sinnvoll ist.


Wie hier geschrieben, qsort ist standardisiert (C99), aber qsort_r ist eine GNU-Erweiterung ("qsort_r() wurde glibc in Version 2.8 hinzugefügt"). Es gibt also keine Anforderungen dafür, dass es auf allen Plattformen gleich ist, geschweige denn portabel.


Linux
  1. Installieren Sie python-openstackclient unter Linux und Mac OS

  2. In welchen Sprachen sind Windows, Mac OS X und Linux geschrieben?

  3. Was ist der Unterschied zwischen env und set (unter Mac OS X oder Linux)?

  4. Rekursives Suchen und Ersetzen in Textdateien auf Mac und Linux

  5. Was ist eine XPerf-Alternative für Linux und Mac OS X?

Verschiedene Möglichkeiten zum Planen und Auflisten von CRON-Jobs in Linux

Linux-Kernel vs. Mac-Kernel

Mit NitroShare können Sie Dateien ganz einfach zwischen Linux, Windows und Mac austauschen

So installieren Sie Linux auf einem Macintosh und booten doppelt mit macOS

So löschen Sie den Bash-Verlauf in Linux und Mac

Binäre Kompatibilität zwischen Mac OS X und Linux