C ++ std :: string und NULL const char *

8

Ich arbeite in C ++ mit zwei großen Code-Stücken, eines im "C-Stil" und eines im "C-Stil".

Der C-Typ-Code hat Funktionen, die const char * zurückgeben, und der C ++ - Code hat an vielen Stellen Dinge wie

%Vor%

Hier wird die Zeichenkette aus einem const char * erstellt, das vom C-Stil-Code zurückgegeben wird.

Dies funktionierte, bis sich der C-Stil-Code änderte und manchmal mit der Rückgabe von NULL-Zeigern begann. Dies verursacht natürlich Seg-Fehler.

Es gibt eine Menge Code herum und so möchte ich die meisten sparsamen Weg zu diesem Problem beheben. Das erwartete Verhalten ist, dass imacppstring in diesem Fall die leere Zeichenfolge ist. Gibt es eine schöne, glatte Lösung?

Aktualisieren

Das von diesen Funktionen zurückgegebene const char * ist immer ein Zeiger auf statische Strings. Sie wurden hauptsächlich verwendet, um informative Nachrichten (die am wahrscheinlichsten für die Protokollierung bestimmt sind) über unerwartetes Verhalten in der Funktion zu übermitteln. Es wurde entschieden, dass das Zurückgeben von NULL auf "nichts zu berichten" nett war, weil dann der Rückgabewert als Bedingung verwendet werden könnte, d. H.

%Vor%

während vor den Funktionen die statische Zeichenfolge "";

zurückgegeben wurde

Ob das eine gute Idee war, ich werde diesen Code nicht anfassen und es liegt sowieso nicht an mir.

Was ich vermeiden wollte, war, jede String-Initialisierung aufzuspüren, um eine Wrapper-Funktion hinzuzufügen.

    
pythonic metaphor 12.11.2009, 17:59
quelle

7 Antworten

13

Wahrscheinlich ist es am besten, die C-Bibliotheksfunktionen an ihr vorbereitendes Änderungsverhalten anzupassen. aber vielleicht hast du keine Kontrolle über diese Bibliothek.

Als zweites müssen Sie alle Instanzen ändern, in denen Sie von den C-Funktionen abhängig sind und eine leere Zeichenfolge zurückgeben, um eine Wrapper-Funktion zu verwenden, die die NULL-Zeiger "repariert":

%Vor%

So jetzt

%Vor%

könnte so aussehen:

%Vor%

Wenn das inakzeptabel ist (es könnte eine Menge Arbeit sein, aber es sollte eine einmalige mechanische Änderung sein), könnten Sie eine "parallele" Bibliothek implementieren, die die gleichen Namen wie die C-Bibliothek hat, die Sie gerade verwenden , wobei diese Funktionen einfach die ursprünglichen C lib-Funktionen aufrufen und die NULL-Zeiger entsprechend korrigieren. Sie müssten einige knifflige Spiele mit Kopfzeilen, Linkern und / oder C ++ - Namespaces spielen, um dies zum Laufen zu bringen, und dies hat ein großes Potenzial, um Verwirrung auf der Straße zu verursachen, also würde ich nachdenken, bevor ich diesen Weg gehe .

Aber etwas wie das Folgende könnte Sie zum Einstieg bringen:

%Vor%

Jetzt müssen Sie nur den Header zu den .cpp-Dateien hinzufügen, die gerade aufrufen, indem Sie die C lib-Funktionen aufrufen (und wahrscheinlich den Header für die C-lib entfernen) und ein

hinzufügen %Vor%

mit diesen Funktionen in die CPP-Datei einfügen.

Das ist vielleicht nicht zu schlecht. Vielleicht.

    
Michael Burr 12.11.2009, 18:54
quelle
6

Nun, ohne jede Stelle zu ändern, an der ein C ++ std::string direkt von einem C-Funktionsaufruf initialisiert wird (um die Nullzeigerüberprüfung hinzuzufügen), wäre die einzige Lösung zu verhindern, dass Ihre C-Funktionen Nullzeiger zurückgeben.

Im GCC-Compiler können Sie eine Compiler-Erweiterung "Conditionals with Omitted Operands" verwenden, um ein Wrapper-Makro für Ihre C-Funktion zu erstellen

%Vor%

aber im allgemeinen Fall würde ich davon abraten.

    
AnT 12.11.2009 18:05
quelle
3

Ich nehme an, Sie könnten einfach eine Wrapper-Funktion hinzufügen, die nach NULL sucht und eine leere std :: string zurückgibt. Aber noch wichtiger: Warum geben Ihre C-Funktionen jetzt NULL zurück? Was bedeutet ein NULL-Zeiger? Wenn es einen schwerwiegenden Fehler anzeigt, möchte Ihre Wrapper-Funktion möglicherweise eine Ausnahme auslösen.

Um sicher zu sein, könnten Sie einfach nach NULL suchen, den NULL-Fall behandeln und erst dann eine std :: string erstellen.

%Vor%     
Charles Salvia 12.11.2009 18:01
quelle
2

Für eine portable Lösung:

(a) Definieren Sie Ihren eigenen String-Typ. Der größte Teil ist ein Suchen und Ersetzen über das gesamte Projekt - das kann einfach sein, wenn es immer std :: string oder großer einmaliger Schmerz ist. (Ich würde die einzige Anforderung stellen, dass es Liskov ist - ersetzbar für eine std :: string, aber auch eine leere Zeichenfolge aus einem null char * konstruiert.

Die einfachste Implementierung erbt öffentlich von std :: string. Auch wenn das (aus verständlichen Gründen) verpönt ist, wäre es in diesem Fall in Ordnung und hilft auch bei Bibliotheken von Drittanbietern, die ein std::string erwarten, sowie Debug-Tools. Alternativ aggegate und vorwärts - yuck.

(b) #define std :: string als eigenen String-Typ. Riskant, nicht zu empfehlen. Ich würde es nicht tun, wenn ich die involvierten Codebasen nicht sehr gut kenne und Ihnen jede Menge Arbeit erspart (und ich würde einige Haftungsausschlüsse hinzufügen, um die Überreste meines Rufs zu schützen;))

(c) Ich habe ein paar solcher Fälle bearbeitet, indem ich den Angriffstyp nur für den Zweck des Includes auf eine Utility-Klasse definiert habe (daher ist der #define-Bereich viel begrenzter). Ich habe jedoch keine Ahnung, wie man das für char * macht.

(d) Schreiben Sie einen Import-Wrapper. Wenn die C-Bibliothekskopfzeilen ein recht normales Layout aufweisen und / oder Sie jemanden kennen, der Erfahrung mit der Analyse von C ++ - Code hat, können Sie möglicherweise einen "Wrapper-Header" generieren.

(e) Bitten Sie den Besitzer der Bibliothek, den Wert "Null-Zeichenfolge" mindestens zur Zeit der Kompilierung konfigurierbar zu machen. (Eine akzeptable Anfrage seit dem Wechsel zu 0 kann die Kompatibilität auch in anderen Szenarien beeinträchtigen.) Sie könnten sogar vorschlagen, die Änderung selbst zu senden, wenn das weniger für Sie ist!

    
peterchen 12.11.2009 18:48
quelle
2

Sie könnten alle Ihre Aufrufe an C-stlye-Funktionen in so etwas umwandeln ...

%Vor%

Dann wo immer Sie haben:

%Vor%

Ersetzen Sie es durch:

%Vor%

Dies setzt natürlich voraus, dass das Konstruieren einer leeren Zeichenfolge ein akzeptables Verhalten ist, wenn Ihre Funktion NULL zurückgibt.

    
JohnMcG 12.11.2009 18:54
quelle
1

Ich befürworte generell keine Unterklassen-Standardcontainer, aber in diesem Fall könnte es funktionieren.

%Vor%     
Mark Ransom 12.11.2009 18:33
quelle
0

So etwas sollte Ihr Problem beheben.

%Vor%

Wenn Sie möchten, können Sie die Fehlerüberprüfungslogik in einer eigenen Funktion speichern. Sie müssten diesen Codeblock dann an weniger Stellen platzieren.

    
Carl Norum 12.11.2009 18:04
quelle

Tags und Links