C ++ ¿Por qué esta matriz pasada por referencia genera un error de tiempo de ejecución?

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

  •  19-08-2019
  •  | 
  •  

Pregunta

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

                   }

           } 

y la llamada ..

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

Es importante para mí pasar matrizSinonimos por referencia.

Editar: quitó el & amp; de & amp; matrizSinonimos .

Editar: el error de tiempo de ejecución es:

An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
¿Fue útil?

Solución

¿Qué tiene de malo?

El código tal como lo tienes allí, no puedo encontrar un error. El único problema que veo es que si no proporciona ningún número, esta parte causará daños:

(synsAux.size()-1)

Restará uno de 0u. Eso se ajustará, porque size () devuelve un tipo entero sin signo. Terminará con un valor muy grande, alrededor de 2 ^ 16 o 2 ^ 32. Debe cambiar la condición while completa a

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

Puede intentar buscar un error en el lado de la llamada. A menudo sucede que hay un desbordamiento del búfer o corrupción del montón en algún lugar antes de eso, y el programa se bloquea en un punto posterior del programa como resultado de eso.

El argumento y los parámetros incluidos en él

Con respecto a la matriz y cómo se pasa, creo que lo haces bien. Aunque, todavía pasa la matriz por valor. Tal vez ya lo sabes, pero lo repetiré. Realmente pasa un puntero al primer elemento de esta matriz:

char matrizSinonimos[1024][1024];

Una matriz 2d realmente es una matriz de matrices. El primer elemento de esa matriz es una matriz, y un puntero a ella es un puntero a una matriz. En ese caso, es

char (*)[1024]

Aunque en la lista de parámetros dijiste que aceptas una matriz de matrices, el compilador, como siempre, lo ajusta y lo convierte en un puntero al primer elemento de dicha matriz. Entonces, en realidad, su función tiene el prototipo, después de que el compilador realiza los ajustes de los tipos de argumento:

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

Aunque a menudo se sugiere, no puede pasar esa matriz como char** , porque la función llamada necesita el tamaño de la dimensión interna, para abordar correctamente las sub-dimensiones a la derecha compensaciones. Trabajando con un char ** en la función llamada, y luego escribiendo algo como matrizSinonimos [0] [1] , intentará interpretar el primer tamaño de (char ** ) caracteres de esa matriz como puntero, e intentará desreferenciar una ubicación de memoria aleatoria, luego lo hará por segunda vez, si no se bloqueó en el medio. No hagas eso . Tampoco es relevante qué tamaño había escrito en la dimensión exterior de esa matriz. Se racionalizó lejos. Ahora, no es realmente importante pasar la matriz por referencia. Pero si quieres, tienes que cambiar todo a

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

Pasar por referencia no pasa un puntero al primer elemento: se conservan todos los tamaños de todas las dimensiones y se pasa el objeto de matriz en sí, en lugar de un valor.

Otros consejos

Las matrices se pasan como punteros; no es necesario hacer una referencia de paso a ellas. Si declara que su función es:

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

Sus cambios en la matriz persistirán: las matrices nunca se pasan por valor.

¡La excepción es probablemente 0xC00000FD , o un desbordamiento de pila!

El problema es que está creando una matriz de 1 MB en la pila, que probablemente sea demasiado grande.

intente declararlo como:

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

Creo que eso hará lo que quieras hacer. La forma en que lo tiene, como han dicho otros, crea una matriz de 1 MB en la pila. Además, al cambiar la sincronización de string a const string & amp; se elimina la inserción de una copia de cadena completa en la pila.

Además, usaría algún tipo de clase para encapsular matrizSinonimos. Algo así como:

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

entonces no tienes que pasarlo en absoluto.

No sé qué tiene de malo el código anterior, pero si no puede hacer que funcione la sintaxis de la matriz, siempre puede hacer esto:

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

También puede reemplazar el tamaño de fila y el tamaño de colsize con un #define SYNONYM_ARRAY_DIMENSION 1024 si se conoce en tiempo de compilación, lo que hará que la multiplicación sea más rápida.

( edit 1 ) Olvidé responder tu pregunta real. Bueno: después de haber corregido el código para pasar la matriz de la manera correcta (ya no hay indirección incorrecta), me parece más probable que no haya verificado sus entradas correctamente. Lees de una secuencia, la guardas en un vector, pero nunca verificaste si todos los números que obtienes están realmente en el rango correcto. ( finalizar edición 1 )

Primero : El uso de matrices sin formato puede no ser lo que realmente desea. Hay std :: vector o boost :: array . El último es una matriz de tamaño fijo en tiempo de compilación como una matriz en bruto, pero proporciona los métodos y definiciones de tipo de colección C ++, lo cual es práctico para el código genérico (leer: templatizado).

Y, al usar esas clases, puede haber menos confusión acerca de la seguridad de tipos, pasar por referencia, por valor o pasar un puntero.

Segundo : Las matrices se pasan como punteros, el puntero se pasa por valor.

Tercero : Debería asignar objetos tan grandes en el montón. La sobrecarga de la asignación del montón es en tal caso insignificante, y reducirá la posibilidad de quedarse sin espacio de pila.

Cuarto :

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

realmente es:

( edit 2 ) Gracias a los comentarios:

void someFunction (int ** array);

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

Ojalá no me haya equivocado en otro lado ... ( finalizar edición 2 )

La información de tipo para ser una matriz de 10x10 se pierde. Para obtener lo que probablemente ha querido decir, debe escribir:

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

De esta forma, el compilador puede comprobar que, en el lado del llamante, la matriz es realmente una matriz de 10x10. Luego puede llamar a la función de esta manera:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top