C ++ Por que essa matriz de referência passada gera um erro de tempo de execução?

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

  •  19-08-2019
  •  | 
  •  

Pergunta

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 a chamada ..

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

É importante para mim passar matrizSinonimos por referência.

Editar: tirou o & de de &matrizSinonimos.

EDIT: O erro de tempo de execução é:

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

Solução

O que há de errado com isso

O código como você o tem lá - não consigo encontrar um bug. O único problema que detesto é que, se você não fornecer nenhum número, essa parte causará danos:

(synsAux.size()-1)

Ele subtrairá um de 0U. Isso vai se envolver, porque size() Retorna um tipo inteiro não assinado. Você acabará com um valor muito grande, em torno de 2^16 ou 2^32. Você deve mudar o todo, condição para

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

Você pode tentar procurar um bug ao redor do lado da chamada. Muitas vezes, isso acontece, há um excesso de buffer ou corrupção de heap em algum lugar antes disso, e o programa trava em um ponto posterior do programa como resultado disso.

O argumento e o material de parâmetro nele

Em relação à matriz e como ela foi passada, acho que você faz isso bem. Embora você ainda passe a matriz por valor. Talvez você já saiba, mas eu vou repetir. Você realmente passa um ponteiro para o primeiro elemento desta matriz:

char matrizSinonimos[1024][1024];

Uma matriz 2D é realmente uma variedade de matrizes. O primeiro leme dessa matriz é uma matriz, e um ponteiro é um ponteiro para uma matriz. Nesse caso, é

char (*)[1024]

Embora na lista de parâmetros você tenha dito que aceita uma matriz de matrizes, o compilador, como sempre, ajusta isso e o torna um ponteiro para o primeiro elemento dessa matriz. Portanto, na realidade, sua função tem o protótipo, após a realização dos ajustes dos tipos de argumento pelo compilador:

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

Embora muitas vezes sugerido, Você não pode passar essa matriz como um char**, porque a função chamada precisa do tamanho da dimensão interna, para abordar corretamente as subdimensões nos compensações direito. Trabalhando com um char** na função chamada, e depois escrevendo algo como matrizSinonimos[0][1], ele tentará interpretar os primeiros caracteres de tamanho de (char **) dessa matriz como um ponteiro e tentará desreferenciar um local aleatório da memória e, em seguida, fazer isso pela segunda vez, se não falhar. Não faça isso. Também não é relevante qual tamanho você escreveu na dimensão externa dessa matriz. Racionalizou. Agora, não é realmente importante passar na matriz por referência. Mas se você quiser, você tem que mudar tudo para

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

A passagem por referência não passa um ponteiro para o primeiro elemento: todos os tamanhos de todas as dimensões são preservados e o próprio objeto da matriz, em vez de um valor, é passado.

Outras dicas

Matrizes são passadas como dicas-não há necessidade de fazer uma referência por eles. Se você declarar sua função:

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

Suas alterações na matriz persistirão - as matrizes são Nunca passado por valor.

A exceção é provavelmente 0xC00000FD, ou um transbordamento de pilha!

O problema é que você está criando uma matriz de 1 MB na pilha, o que provavelmente é muito grande.

Tente declarar como:

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

Eu acredito que isso fará o que você quer. A maneira como você tem, como outros disseram, cria uma matriz de 1 MB na pilha. Além disso, mudando a sinline de string para const string & Elimina empurrar uma cópia completa na pilha.

Além disso, eu usaria algum tipo de classe para encapsular os matrizsinonimos. Algo como:

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

Então você não precisa passar por nada.

Não estou sem querer o que há de errado com o código acima, mas se você não conseguir fazer a sintaxe da matriz funcionar, sempre poderá fazer isso:

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

Você também pode substituir o Rowsize e o Colsize por um #Define Synonym_Array_Dimension 1024 se for conhecido no horário de compilação, o que tornará a etapa de multiplicação mais rápida.

(Editar 1) Esqueci de responder sua pergunta real. Bem: depois que você corrigiu o código para passar a matriz da maneira correta (sem indiramento incorreto mais), parece -me mais provável que você não tenha verificado as entradas corretamente. Você leu de um fluxo, salva -o em um vetor, mas nunca verifica se todos os números que você obtém lá estão realmente no intervalo correto. (End Edit 1)

Primeiro: Usar matrizes brutas pode não ser o que você realmente deseja. Há std::vector, ou boost::array. O último é a matriz de tamanho fixo de tempo de compilação como uma matriz crua, mas fornece as definições e métodos de tipo de coleção C ++, o que é prático para o código genérico (leia: templatizado).

E, usando essas classes, pode haver menos confusão sobre a segurança do tipo, passar por referência, por valor ou passar um ponteiro.

Segundo: As matrizes são passadas como ponteiros, o ponteiro em si é passado pelo valor.

Terceiro: Você deve alocar objetos tão grandes na pilha. A sobrecarga da alocação de heap é, nesse caso, insignificante e reduzirá a chance de ficar sem o espaço da pilha.

Quarto:

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

Realmente é:

(Editar 2) Graças aos comentários:

vazio alguma função (int ** matriz);

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

Espero não ter estragado em outro lugar .... (End Edit 2)

A informação de tipo é uma matriz de 10x10 é perdida. Para conseguir o que você provavelmente quis dizer, você precisa escrever:

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

Dessa forma, o compilador pode verificar se, no lado do chamador, a matriz é na verdade uma matriz de 10x10. Você pode chamar a função assim:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top