C ++ Por que essa matriz de referência passada gera um erro de tempo de execução?
-
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]
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;
}