C ++ Perché questa matrice passata per riferimento genera un errore di runtime?

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

  •  19-08-2019
  •  | 
  •  

Domanda

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';

                   }

           } 

e la chiamata ..

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

È importante per me passare matrizSinonimos per riferimento.

Modifica: ha portato via & amp; da & amp; matrizSinonimos .

Modifica: l'errore di runtime è:

An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
È stato utile?

Soluzione

Cosa c'è che non va

Il codice come lo hai lì - non riesco a trovare un bug. L'unico problema che rilevo è che se non fornisci alcun numero, questa parte causerà danni:

(synsAux.size()-1)

Ne sottrarrà uno da 0u. Ciò andrà a finire, perché size () restituisce un tipo intero senza segno. Ti ritroverai con un valore molto grande, intorno a 2 ^ 16 o 2 ^ 32. Dovresti cambiare la condizione while intera in

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

Puoi provare a cercare un bug sul lato chiamata. Accade spesso che si verifichi un buffer overflow o un danneggiamento dell'heap da qualche parte prima e il programma si arresta in modo anomalo in un secondo momento nel programma a causa di ciò.

Argomenti e parametri al suo interno

Per quanto riguarda l'array e il modo in cui è passato, penso che tu lo faccia bene. Tuttavia, si passa comunque l'array per valore. Forse lo sai già, ma lo ripeterò. Passi davvero un puntatore al primo elemento di questo array:

char matrizSinonimos[1024][1024];

Un array 2d è davvero un array di array. Il primo lement di quell'array è un array e un puntatore ad esso è un puntatore a un array. In tal caso, lo è

char (*)[1024]

Anche se nella lista dei parametri hai detto che accetti un array di array, il compilatore, come sempre, lo regola e lo rende un puntatore al primo elemento di tale array. Quindi, in realtà, la tua funzione ha il prototipo, dopo aver apportato le modifiche ai tipi di argomento da parte del compilatore:

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

Anche se spesso suggerito, Non puoi passare quell'array come char** , perché la funzione chiamata ha bisogno della dimensione della dimensione interna, per indirizzare correttamente le dimensioni inferiori agli offset giusti. Lavorando con un char ** nella funzione chiamata, quindi scrivendo qualcosa come matrizSinonimos [0] [1] , proverà ad interpretare la prima dimensione di (char ** ) caratteri di quell'array come puntatore e proverà a dereferenziare una posizione di memoria casuale, quindi farlo una seconda volta, se non si è bloccato in mezzo. Non farlo . Inoltre, non è rilevante quale dimensione hai scritto nella dimensione esterna di quella matrice. Si è razionalizzato. Ora, non è molto importante passare l'array per riferimento. Ma se vuoi, devi cambiare tutto in

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

Il passaggio per riferimento non passa un puntatore al primo elemento: vengono mantenute tutte le dimensioni di tutte le dimensioni e viene passato l'oggetto array stesso, anziché un valore.

Altri suggerimenti

Le matrici vengono passate come puntatori: non è necessario eseguirne un riferimento pass-by. Se dichiari che la tua funzione è:

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

Le modifiche apportate all'array persistono: le matrici non sono mai passate per valore.

L'eccezione è probabilmente 0xC00000FD o un overflow dello stack!

Il problema è che stai creando un array da 1 MB nello stack, che probabilmente è troppo grande.

prova a dichiararlo come:

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

Credo che farà quello che vuoi fare. Il modo in cui lo hai, come altri hanno già detto, crea un array da 1 MB nello stack. Inoltre, cambiando la linea di sincronizzazione da string a const string & amp; si elimina l'invio di una copia di stringa completa nello stack.

Inoltre, userei una sorta di classe per incapsulare matrizSinonimos. Qualcosa del tipo:

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

quindi non è necessario passarlo affatto.

Sono in perdita per ciò che non va nel codice sopra, ma se non riesci a far funzionare la sintassi dell'array, puoi sempre farlo:

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 );

Potresti anche sostituire le dimensioni delle righe e delle dimensioni con un #define SYNONYM_ARRAY_DIMENSION 1024 se è noto al momento della compilazione, il che renderà il passaggio di moltiplicazione più veloce.

( modifica 1 ) Ho dimenticato di rispondere alla tua vera domanda. Bene: dopo aver corretto il codice per passare l'array nel modo corretto (nessuna indiretta più errata), mi sembra molto probabile che tu non abbia verificato correttamente gli input. Leggi da un flusso, lo salvi in ??un vettore, ma non hai mai verificato se tutti i numeri che hai lì sono effettivamente nell'intervallo corretto. ( fine modifica 1 )

prima : L'utilizzo di array grezzi potrebbe non essere quello che desideri effettivamente. Ci sono std :: vector o boost :: array . Quest'ultimo è un array a dimensione fissa in fase di compilazione come un array non elaborato, ma fornisce la raccolta C ++ di tipo def e metodi, che è pratico per il codice generico (leggi: templatized).

E, usando quelle classi potrebbe esserci meno confusione sulla sicurezza dei tipi, passare per riferimento, per valore o passare un puntatore.

Secondo : Le matrici vengono passate come puntatori, il puntatore stesso viene passato per valore.

Terzo : Dovresti allocare oggetti così grandi sull'heap. Il sovraccarico dell'allocazione dell'heap è in questo caso insignificante e ridurrà la possibilità di rimanere senza spazio nello stack.

Quarto :

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

è davvero:

( modifica 2 ) Grazie ai commenti:

void someFunction (int ** array);

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

Spero di non aver rovinato altrove ... ( end edit 2 )

Le informazioni sul tipo per essere un array 10x10 vanno perse. Per ottenere ciò che probabilmente intendevi, devi scrivere:

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

In questo modo il compilatore può verificare che sul lato chiamante l'array sia effettivamente un array 10x10. È quindi possibile chiamare la funzione in questo modo:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top