C ++ Warum ist dies weitergegeben-by-Referenzfeld einen Laufzeitfehler zu erzeugen?

StackOverflow https://stackoverflow.com/questions/469892

  •  19-08-2019
  •  | 
  •  

Frage

void pushSynonyms (string synline,  char  matrizSinonimos [1024][1024]){


             stringstream synstream(synline);

             vector<int> synsAux;


             int num;

             while (synstream >> num) {synsAux.push_back(num);}


             int index=0;
             while (index<(synsAux.size()-1)){

                   int primerSinonimo=synsAux[index];
                   int segundoSinonimo=synsAux[++index];
                   matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
                   matrizSinonimos [segundoSinonimo][primerSinonimo]='S';

                   }

           } 

und der Anruf ..

char matrizSinonimos[1024][1024];
     pushSynonyms("1 7", matrizSinonimos)

Es ist wichtig für mich matrizSinonimos durch Verweis übergeben.

Edit: wegnahm die & von &matrizSinonimos

.

Edit: die Laufzeitfehler ist:

An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
War es hilfreich?

Lösung

Was ist falsch daran

Der Code, wie Sie es dort haben - ich kann nicht einen Fehler finden. Das einzige Problem, das ich vor Ort ist, dass, wenn Sie überhaupt keine Zahl zur Verfügung stellen, dann ist dieser Teil Schaden verursachen wird:

(synsAux.size()-1)

Es wird ein von 0HE subtrahieren. Das wird umschlingen, weil size() gibt einen unsigned Integer-Typ. Sie werden mit einem sehr großen Wert am Ende, irgendwo um 2 ^ 16 oder 2 ^ 32. Sie sollten die ganze während Bedingung

ändern
while ((index+1) < synsAux.size())

Sie können versuchen, für einen Fehler um den Anruf Seite suchen. Oft passiert es, gibt es einen Pufferüberlauf oder Heapbeschädigung irgendwo davor, und das Programm stürzt ab, zu einem späteren Zeitpunkt im Programm als Folge davon.

Das Argument und Parameter Sachen drin

In Bezug auf das Array und wie es passiert ist, ich glaube, Sie tun es in Ordnung. Obwohl, übergeben Sie immer noch das Array von Wert. Vielleicht wissen Sie es schon, aber ich werde es wiederholen. Sie wirklich einen Zeiger auf das erste Element dieses Array übergeben werden:

char matrizSinonimos[1024][1024];

Eine 2D-Array ist wirklich ein Array von Arrays. Die erste lement dieser Anordnung ist ein Array, und ein Zeiger auf das ein Zeiger auf ein Array. In diesem Fall ist es

char (*)[1024]

Obwohl in der Parameterliste Sie gesagt, dass Sie ein Array von Arrays akzeptieren, den Compiler, wie immer, dass passt und einen Zeiger auf das erste Element einer solchen Anordnung machen. Also in Wirklichkeit Ihre Funktion den Prototyp hat, nachdem die Anpassungen der Argumenttypen vom Compiler getan werden:

void pushSynonyms (string synline,  char (*matrizSinonimos)[1024]);

Obwohl oft vorgeschlagen, Sie können nicht das Array als char** geben , weil die aufgerufene Funktion die Größe der inneren Dimension benötigt, richtig Subdimensionen an den richtigen Offsets zu adressieren. Das Arbeiten mit einem char** in der aufgerufenen Funktion, und dann so etwas wie matrizSinonimos[0][1] schreibt, wird es versuchen, die erste sizeof (char **) Zeichen des Arrays als Zeiger zu interpretieren, und wird versuchen, zu dereferenzieren einer zufälligen Speicherstelle zu tun, dann ist das ein zweites Mal, wenn es zum Absturz in nicht zwischen. Tu das nicht . Es ist auch nicht relevant, welche Größe Sie in der äußeren Dimension des Arrays geschrieben hatten. Es wegrationalisiert. Nun, es ist nicht wirklich wichtig, das Array als Verweis zu übergeben. Aber wenn Sie wollen, müssen Sie die gesamte thingn ändern

void pushSynonyms (string synline,  char (&matrizSinonimos)[1024][1024]);

Passing durch Verweis keinen Zeiger auf das erste Element passieren: Alle Größen aller Dimensionen erhalten bleiben, und das Array-Objekt selbst, sondern als ein Wert, übergeben wird.

Andere Tipps

Arrays als Zeiger übergeben - es gibt keine Notwendigkeit, einen Pass-by-reference ihnen zu tun. Wenn Sie Ihre Funktion erklären sein:

void pushSynonyms(string synline, char matrizSinonimos[][1024]);

Ihre Änderungen an dem Array wird anhalten -. Arrays sind nie von Wert übergeben

Die Ausnahme wahrscheinlich 0xC00000FD wird, oder ein Stapelüberlauf!

Das Problem ist, dass Sie einen 1 MB-Array auf dem Stapel erstellen, die wahrscheinlich zu groß ist.

versuchen, es so zu erklären:

void pushSynonyms (const string & synline,  char  *matrizSinonimos[1024] )

Ich glaube, dass das tun, was Sie tun mögen. Die Art und Weise haben Sie es, wie andere gesagt haben, schafft einen 1MB-Array auf dem Stapel. Auch synline von string Wechsel eliminiert const string & eine vollständige Zeichenfolge Kopie auf den Stapel schieben.

Auch würde ich eine Art von Klasse verwenden matrizSinonimos zu verkapseln. So etwas wie:

class ms
{
    char m_martix[1024][1024];
    public:
    pushSynonyms( const string & synline );
}

, dann haben Sie es nicht passieren überhaupt.

Ich bin an einem Verlust für das, was oben mit dem Code falsch ist, aber wenn Sie nicht die Array-Syntax bekommen zu arbeiten, können Sie immer tun:

void pushSynonyms (string synline,  char  *matrizSinonimos, int rowsize, int colsize )
{
   // the code below is equivalent to 
   // char c = matrizSinonimos[a][b];
   char c = matrizSinonimos( a*rowsize + b );
   // you could also Assert( a < rowsize && b < colsize );
}

pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );

Sie können auch Zeilengröße und colsize mit einem #define SYNONYM_ARRAY_DIMENSION 1024 ersetzen, wenn es zum Zeitpunkt der Kompilierung bekannt ist, was die Multiplikation Schritt schneller machen wird.

( Bearbeiten 1 ) Ich habe vergessen, Ihre eigentliche Frage zu beantworten. Well: nachdem Sie den Code korrigiert haben das Array in der richtigen Art und Weise (keine falsche indirection mehr) zu passieren, so scheint es sehr wahrscheinlich zu mir, dass Sie nicht, dass Sie Eingaben haben überprüfen richtig. Sie lesen aus einem Stream, es in einen Vektor speichern, aber Sie nie geprüft, ob alle Zahlen, die Sie dort im richtigen Bereich tatsächlich bekommen sind. ( Ende bearbeiten 1 )

Erste : raw Arrays kann nicht sein, was Sie eigentlich wollen. Es gibt std::vector oder boost::array. Letzteres ist Compiler-feste Größe Array wie ein rohes-Array, sondern stellt den C ++ Sammlung Typ-defs und Methoden, die für generische (sprich: templatized) praktisch ist. Code

Und diese Klassen es weniger Verwirrung über Typsicherheit sein kann, durch Verweis übergeben, nach Wert oder einen Zeiger übergeben.

Zweite : Arrays werden als Zeiger übergeben, der Zeiger selbst von Wert übergeben wird.

Dritte : Sie sollten so große Objekte auf dem Heap zugewiesen werden. Der Overhead des Haufens-Zuteilung ist in einem solchen Fall unbedeutend, und es wird die Möglichkeit des Laufens aus Stack-Raum zu reduzieren.

Vierte :

void someFunction(int array[10][10]);

wirklich ist:

( bearbeiten 2 ) Dank der Kommentare:

void Funktion (int ** array);

void someFunction(int (*array)[10]);

Hoffentlich habe ich Schraube nicht an anderer Stelle nach oben .... ( Ende bearbeitet 2 )

Die Typ-Informationen eine 10x10-Array verloren. Zu bekommen, was Sie wahrscheinlich gemeint haben, müssen Sie schreiben:

void someFunction(int (&array)[10][10]);

Auf diese Weise der Compiler, dass auf der Anruferseite das Array überprüfen kann, ist tatsächlich ein 10x10-Array. Anschließend können Sie die Funktion wie folgt aufrufen:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top