Alocação dinamica SIGSEGV [RESOLVIDO]

1. Alocação dinamica SIGSEGV [RESOLVIDO]

Paulo
paulo_moc

(usa Ubuntu)

Enviado em 11/04/2013 - 09:36h

Olá pessoal, estav criando uma classe mapa para testar colisões pelo mapa, tenho uma matriz de inteiro(o mapa) que é alocada dinamicamente no construtor da classe, até a funciona, usei o debugger os valores estão corretos, mas na hora de acessar o valor de uma posição, eu recebo um sigsegv:

http://codepad.org/MTxejW7u


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 11/04/2013 - 17:39h

Seu código tem uma quantidade razoável de bugs, a saber:

1) Na primeira chamada a calloc(), você errou o tipo passado ao operador sizeof: deveria ter sido int*, não int.

2) Caso ocorra um erro na alocação das colunas em cada linha, você deveria desalocar as linhas anteriores já alocadas e também o mapa antes de lançar a exceção.

3) Na chamada que faz a memset(), você faz algo muito perigoso ao assumir que as colunas de cada linha vão ficar em posições de memória contíguas. Para alocação dinãmica na forma como você fez, provavelmente não será verdade. (EDIT: Aliás, o tamanho usado nesse memset() é idêntico a sizeof(int). Você provavelmente quis dizer -- ainda erroneamente -- sizeof(int)*this->altura*this->largura, não?)

4) Chamar calloc(), que gasta tempo preenchendo a memória alocada com zeros, para depois chamar memset() com outro valor é, mesmo que não tivesse o bug relatado acima, desperdício. Teria sido melhor, nesse caso, ter usado malloc(), que só aloca a área, mas não se preocupa de preecnhê-la com valor algum.

--------

Já que está usando C++, por que não usa std::vector? Você poderia declarar o membro mapa com

std::vector< std::vector<int> > mapa; 


e fazer a inicialização, dentro do contrutor da sua classe, do seguinte modo.

mapa.resize(altura, std::vector<int>(largura, NADA)); 


Só uma linha já lhe dá a alocação de todos os elementos e os preenche com um valor inicial. Se ocorrer uma falha de alocação a qualquer momento, você não precisa de se preocupar em testá-la manualmente, nem com desalocar os dados parcialmente alocados. Você não vai sequer precisar de colocar desalocação explicitamente no destrutor.

Leia sobre std::vector.

--------

Se você quiser mesmo, com fins didáticos (ou por masoquismo), usar arrays nativos e alocação dinâmica explícita, é geralmente mais conveniente e recomendável usar o operador nativo new[] do que calloc() ou malloc(), pois o compilador já lhe daria certezas quanto ao tipo do dado alocado, sem o risco de cometer o primeiro dos erros que eu indiquei acima.

O código abaixo tenta corrigir todos os bugs, usando a forma C++ de alocação dinâmica. Veja como, apesar de inchado para tratar o segundo bug, o código com new[] ficaria mais "limpo" por dispensar aqueles casts supérfluos e não ter necessidade de ifs para testar se cada alocação foi ou não bem sucedida para, dependendo do caso, lançar manualmente uma exceção.

Mapa::Mapa() { // construtor
// inicializa primeiro os elementos que nao dependam de mapa.
// bla bla bla...

// mapa deve ter sido declarado como "int **mapa;"
mapa=new int*[altura];
int i=0;
try {
for(; i<altura; i++){
mapa[i]=new int[largura];
fill(mapa[i], mapa[i]+largura, NADA); // fill() fica dentro de <algorithm>
}
}
catch(std::bad_alloc &e){
while(i>0)
delete [] mapa[--i];
delete [] mapa;
throw; // re-dispara a excecao recebida
}

// Continua inicilizacao do objeto no construtor, especialmente
// com coisas contidas no mapa, que agora esta incializado.
// blu blu blu...
}


Não se pode esquecer de colocar o código análogo no destrutor.

Mapa::~Mapa() {
// Desconstroi o que depende do mapa.
// bla bla bla...

// Desconstroi o mapa
for(int i=altura; i>0; )
delete [] mapa[--i];
delete [] mapa;

// Desconstroi o que nao depende do mapa.
// blu blu blu...
}


3. Re: Alocação dinamica SIGSEGV [RESOLVIDO]

???
gokernel

(usa Linux Mint)

Enviado em 11/04/2013 - 10:26h

http://www.cplusplus.com/reference/cstdlib/calloc/




4. Re: Alocação dinamica SIGSEGV [RESOLVIDO]

Paulo
paulo_moc

(usa Ubuntu)

Enviado em 12/04/2013 - 09:03h

Hmm, como sempre muitos bugs hehe... eu tinha visto um tutorial de como alocar dinamicamente usando calloc aqui no fórum(ele não usava memset), mas agradeço a ajuda, já esta funcionando e a colisão também, muito obrigado pela ajuda.

=]






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts