Ist es sicher, den argv-Zeiger global zu verwenden?

Lesezeit: 7 Minuten

Benutzer-Avatar
Steve Dell

Ist es sicher, die zu verwenden argv Zeiger global? Oder gibt es einen Umstand, wo es ungültig werden kann?

dh: Ist dieser Code sicher?

char **largs;
void function_1()
{
    printf("Argument 1: %s\r\n",largs[1]);
}
int main(int argc,char **argv)
{
    largs = argv;
    function_1();
    return 1;
}

  • Nein, der Code ist nicht gespeichert. Das Programm kann ohne Argumente aufgerufen werden, also nur argv[0] oder große[0] würde eine Zeichenfolge enthalten.

    Benutzer2672107

    24. Juli 2015 um 12:39 Uhr

  • @manni66: Gute Beobachtung, obwohl nicht wirklich der Sinn der Frage: aber Sie könnten es mit so etwas wie beheben if (largs[0] && largs[1]).

    – Nate Eldredge

    24. Juli 2015 um 13:47 Uhr

  • @NateEldredge: Was lässt dich das denken largs[1] wäre null wenn argc==1 ? Das OP muss nur ein globales machen int largsc; und weise es zu largsc = argc in main(), genau wie er es für getan hat largs. Dann function_1() hat Zugriff auf nicht nur das Programm argvsondern auch seine argc.

    – Telefontagger

    24. Juli 2015 um 20:03 Uhr

  • @phonetagger: C89 2.1.2.2, das ist was. (Oder C99 5.1.2.2.1.) “argv[argc] soll ein Nullzeiger sein.” Natürlich können Sie auch tun, was Sie vorschlagen, aber es ist oft bequem, die Tatsache auszunutzen, dass argv ist garantiert nullterminiert.

    – Nate Eldredge

    24. Juli 2015 um 20:33 Uhr


  • @NateEldredge: Autsch, das tat weh! 🙂 Ich habe das niemals gewusst. Das hätte im Laufe der Jahre vielleicht einige Dinge vereinfacht, wenn ich es getan hätte. Danke für die Information.

    – Telefontagger

    24. Juli 2015 um 20:36 Uhr

Benutzer-Avatar
TartanLama

Ja, es ist sicher zu verwenden argv global; Sie können es wie jedes andere verwenden char** in deinem Programm. Der C99-Standard spezifiziert dies sogar:

Die Parameter argc und argv und die Zeichenfolgen, auf die durch die hingewiesen wird argv Array soll durch das Programm änderbar sein und ihre zuletzt gespeicherten Werte zwischen Programmstart und Programmende beibehalten.

Der C++-Standard hat keinen ähnlichen Absatz, aber derselbe ist implizit ohne gegenteilige Regel.

Beachten Sie, dass C++ und C verschiedene Sprachen sind und Sie nur eine auswählen sollten, zu der Sie Ihre Frage stellen möchten.

  • Es ist wahrscheinlich, dass das OP beabsichtigte, das Verhalten sowohl in C als auch in C++ zu kennen, nicht in dem einen oder anderen, wenn man bedenkt, dass beide Sprachen verwendet werden argv und er ausdrücklich markiert c und c++ als er die Frage zum ersten Mal gepostet hat 🙂

    – Chris Cirefice

    24. Juli 2015 um 14:48 Uhr

  • Um pedantisch zu sein, argv ist wirklich nur während der Ausführung von vorhanden main()daher kann es zu Problemen beim Zugriff kommen argv in so etwas wie ein atexit() Handler.

    – Lee Daniel Crocker

    24. Juli 2015 um 19:40 Uhr

  • @LeeDanielCrocker Stimmt das? Die Spezifikation kann knifflig sein, aber für mich sah es so aus, als hätte TartanLlama die Spezifikation zitiert und gesagt, dass sie bis zur Beendigung bestehen blieb. Dies würde mir nahelegen, dass der Speicher durch Terminierung verfügbar ist und main () einfach ein Zeiger darauf übergeben wird.

    – Cort Ammon

    25. Juli 2015 um 3:15 Uhr

Benutzer-Avatar
Serge Rogatch

Es sollte so lange sicher sein main() Funktion wird nicht beendet. Ein paar Beispiele für Dinge, die danach passieren können main() Ausgänge sind:

  1. Destruktoren von globalen und statischen Variablen
  2. Threads laufen länger als main()

Gelagert argv dürfen darin nicht verwendet werden.

Die Referenz sagt nichts aus, was Anlass zu der Annahme geben würde, dass die Lebensdauer der Argumente zu hoch ist main() Funktion unterscheiden sich von den allgemeinen Regeln für die Lebensdauer von Funktionsargumenten.

So lange wie argv Zeiger selbst gültig ist, muss die C/C++-Laufzeitumgebung garantieren, dass der Inhalt, auf den dieser Zeiger zeigt, gültig ist (natürlich, es sei denn, irgendetwas beschädigt den Speicher). Es muss also sicher sein, den Zeiger und den Inhalt so lange zu verwenden. Nach main() zurückgibt, gibt es auch für die C/C++-Laufzeit keinen Grund, den Inhalt gültig zu halten. Die obige Argumentation gilt also sowohl für den Zeiger als auch für den Inhalt, auf den er zeigt.

  • Können Sie Referenzen angeben, um dies zu belegen?

    – ComicSansMS

    24. Juli 2015 um 8:39 Uhr

  • @ComicSansMS, nein, das ist nur gesunder Menschenverstand, basierend auf allgemeinen Regeln für die Lebensdauer lokaler Variablen und Parameter: bis zum Verlassen der Funktion, zu der sie gehören.

    – Serge Rogatch

    24. Juli 2015 um 8:44 Uhr

  • @ComicSansMS, ich habe der Referenz einen Link hinzugefügt und die Antwort bearbeitet. Der Punkt ist, dass die Referenz für main() sagt nichts Besonderes über die Lebensdauer seiner Argumente aus, daher ist es vernünftig anzunehmen, dass die Argumente von main() Befolgen Sie die allgemeinen Regeln für Lebenszeiten.

    – Serge Rogatch

    24. Juli 2015 um 8:57 Uhr

  • Ja, es ist ziemlich schwierig, definitive Quellen zu diesem Thema zu finden, deshalb habe ich gefragt. Danke für den Versuch, sehr verbunden.

    – ComicSansMS

    24. Juli 2015 um 9:00 Uhr

  • Bis zu einem gewissen Grad scheinen Ihre Argumente hauptsächlich auf die Lebensdauer des zuzutreffen argv Zeiger selbst (dh wenn Sie einen Zeiger gespeichert hätten zu es aus &argv) und nicht der Inhalt.

    – Random832

    24. Juli 2015 um 12:35 Uhr

ist es sicher, den argv-Zeiger global zu verwenden

Dazu bedarf es noch etwas Aufklärung. Als die C11 spec sagt in Kapitel §5.1.2.2.1, Programmstart

[..].. mit zwei Parametern (hier als argc und argvobwohl beliebige Namen verwendet werden können, da sie lokal für die Funktion sind, in der sie deklariert sind)

Das heißt, die Variablen selbst haben a Umfang begrenzt auf main(). Sie sind nicht global sich.

Wieder sagt der Standard,

Die Parameter argc und argv und die Zeichenfolgen, auf die das argv-Array zeigt, sollen durch das Programm modifizierbar sein und ihre zuletzt gespeicherten Werte zwischen dem Programmstart und der Programmbeendigung beibehalten.

Das heißt, die Lebensdauer dieser Variablen sind bis main() beendet die Hinrichtung.

Wenn Sie also eine globale Variable verwenden, um den Wert von zu halten main()können Sie diese Globals sicher verwenden, um in jeder anderen Funktion darauf zuzugreifen.

  • Besteht “Programmbeendigung” aus dem Ende von main? Oder kann es danach sein?

    – Yakk – Adam Nevraumont

    24. Juli 2015 um 20:18 Uhr

  • @ Yakk Es ist danach, siehe atexit()

    – Michael Christiansen

    25. Juli 2015 um 9:45 Uhr

  • @mikk sicher, das scheint vernünftig: aber es widerspricht der obigen Antwort, und Ich habe kein Standardzitat gesehen, das dies explizit macht. Ist dort eines? Random lieferte in einer anderen Antwort einen beiläufigen Kommentar von jemandem, der möglicherweise im Ausschuss über Absichten ist.

    – Yakk – Adam Nevraumont

    25. Juli 2015 um 12:16 Uhr


  • @Yakk main wird vom Initialisierungsteil des Programms aufgerufen. Das oberste Element des Stapels ist die Rückkehradresse für main, um zu der Routine zurückzukehren, die den Rest des Sterbens behandelt. Das String-Array, auf das argv zeigt, existiert noch bis zum Ende. Wenn jedoch die darin enthaltenen Zeiger neu blockiert wurden, könnten Probleme auftreten.

    – Michael Christiansen

    25. Juli 2015 um 12:43 Uhr

Dieser Faden in der comp.lang.c.moderated-Newsgroup diskutiert das Thema ausführlich aus Sicht des C-Standards, einschließlich eines Zitats, das zeigt, dass der Inhalt der argv-Arrays (und nicht der argv-Zeiger selbst, wenn Sie z. B. eine Adresse genommen haben &argv und gespeichert, die bis “Programmbeendigung” dauern, und eine Behauptung, dass es “offensichtlich” ist, dass die Programmbeendigung in einer dafür relevanten Weise noch nicht aufgetreten ist, während die atexit-registrierten Funktionen ausgeführt werden:

Das Programm wurde während der atexit-registrierten Funktionsverarbeitung nicht beendet. Wir dachten, das sei ziemlich offensichtlich.

(Ich bin mir nicht sicher, wer Douglas A. Gwyn ist, aber es klingt so, als ob „wir“ das C-Standardkomitee bedeutet?)

Der Kontext der Diskussion betraf hauptsächlich das Speichern einer Kopie des Zeigers argv[0] (Programmname).

Der relevante C-Normtext ist 5.1.2.2.1:

Die Parameter argc und argv und die Zeichenfolgen, auf die das argv-Array zeigt, sollen durch das Programm modifizierbar sein und ihre zuletzt gespeicherten Werte zwischen dem Programmstart und der Programmbeendigung beibehalten.

Natürlich ist C++ nicht C, und sein Standard kann sich in diesem Punkt geringfügig unterscheiden oder es nicht ansprechen.

Benutzer-Avatar
ameyCU

Sie können sie entweder als Parameter übergeben oder in speichern global variables. Solange du nicht zurückkommst main und versuchen, sie in einem zu verarbeiten atexit Handler oder der Destruktor einer Variablen im globalen Gültigkeitsbereich, sie sind immer noch vorhanden und können von jedem Gültigkeitsbereich aus problemlos aufgerufen werden.

Benutzer-Avatar
wangli_64604

Ja, es ist sicher für Ether C oder C++, weil es keinen Thread gibt, nachdem main beendet wurde.

1372590cookie-checkIst es sicher, den argv-Zeiger global zu verwenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy