Ir para conteúdo
Fórum Script Brasil
  • 0

Alocação Dinâmica Retorna Ponteiro Inascessivel.


barutaji

Pergunta

Olá, o tópico ficou meio longo, mas é que o problema é meio complicado mesmo...

Estou desenvolvendo um programa que faz diversas operações com algumas matrizes. Como o tamanho das matrizes é desconhecido usei apenas ponteiros e alocação dinâmica. O problema é que o código começou a dar problema a partir de 1 alocação específica (sempre a mesma) em um local do código completamente inesperado. Pesquisei em todo lugar e não tenho a mínima idéia do que poderia ser, então se pudessem me ajudar agradeceria muito.

(a notação é de c++)

Explicação básico do código:

-No futuro ele irá pegar dados de um arquivo, mas por enquanto simplesmente inicializei internamente em getdatafiles().

-O programa só está com as partes de processamento, que ocorrem dentro de treat_data(). Depois que essa função funcionar direito existirão outras de entrada e saída de dados. Talvez eu puxe as funções de processamento para dentro da classe e faça o objeto calcular seus próprios dados.

-Primeiro a array é normalizada em 1 sentido e depois é tirada a média no outro sentido. Para que as funções average() e normalize() sejam mais poderosas e possam ser reutilizadas coloquei um argumento que indica a dimensão "fixa", assim dá pra fazer na vertical ou horizontal.

-Como o problema ocorre dentro de average() as funções pra baixo (dentro de treat_data()) não são nem executadas, então o problema não pode estar nelas.

-Como estavam aparecendo esses erros de execução criei uma funçaõ temporária parray() para imprimi uma array 2D.

#################### O ERRO ENTÃO: ################

Na execução average() é executada 3 vezes. Na primeira e segunda tudo ocorre perfeitamente (com valores testados com parray() ). O problema é na 3 vez: ele dá erro de execução dentro de parray(), pois o operador new retornou um valor != null, mas com endereço que não pode ser acessado. Então coloquei

cout<<"&="<<avg2<<" value="<<*avg2<<endl;

logo depois de avg2 ser criado, e ele digita o texto até o final, mas quando vai digitar o "valor" e acessar o ponteiro o programa trava e não encerra nem com ctrl^c, preciso ir no gerenciador de tarefas (estou com Windows), o mesmo problema que ocorre dentro de parray().

O mais estranho é que o programa já rodou corretamente até o final algumas vezes, mas geralmente trava (sempre no mesmo lugar). Quando rodo em modo Debug(F8) a execução ocorre sempre perfeita. Vai entender...

Recompilei n vezes em 3 computadores tanto com gcc++ e Borland c++5.5, revi o código inteiro, reiniciei o computador, testei valor por valor, pesquisei em tudo que é forum ou site de programação e nada. Meu próximo passo seria tentar abandonar a notaçaõ C++ e usar malloc, mas pra não ter que mudar o código inteiro vou tentar achar uma solução antes. De qualquer modo já utilizei malloc apenas no local do problema e não resolveu, só não tentei subsituir tudo ainda.

Quando o programa roda até o fim (usando debug, por exemplo) vejo que todos os valores calculados estão corretos, ou seja: não existe erro de lógica muito aparente e todas as matrizes são corretamente criadas e acessadas.

O que poderia ser isso???? Agradeço toda ajuda.

###########DETALHES ADICIONAIS##############

Só agora percebi uma coisa: o programa trava se eu indico "*avg2", mas dentro de average existe a linha "avg2[x]=sum/n;" que aparentemente não deu problema nenhum...

Ultima informação: quando ponho pra executar ele aparece usando cerca de 2MB de memória, mas o programa só tem ~450KB e as variáveis não passam de 0,5KB. Esses 2MB não são uma "margem" criada automaticamente pelo Windows, pois o valor flutua ~300KB pra cima e pra baixo, algo que não aconteceria com essa folga toda. Depois que mando parar o processo a memória não é desalocada (cada execução inutiliza 2MB de memória).

Será que isso é virus? Como poderia infectar logo que o programa é compilado?

Alguém poderia me dar uma luz, nem que seja só um palpite, sobre esse erro? Preciso desse código funcionando (na verdade esse é só o começo dele, o resto nem começei a fazer) para meu trabalho de iniciação científica, e se eu nem descobrir porque ocorre fica difícil.

#include <iostream>
using std::cout;
using std::cin;
using std::ios;
using std::cerr;
using std::endl;

#include <fstream>
using std::ofstream;
using std::ifstream;


#include <cstdlib>
#include <cstdio>

#define LIMCRIT 3
#define LIMALT 3

//Classes utilizadas

class Data{
public:
       int numcrit, numalt; //numero de critérios e alternativas.
       int esccrit, escalt; //escala utilizada (de 1 a n).
       double intercrit[LIMCRIT][LIMCRIT]; //array com relaçaõ entre critérios.
       double interalt[LIMCRIT][LIMALT][LIMALT];
              //arrays com rel entre alternativas, segundo critério.
};

class Average{
public:
//ponteiros porque as funções pegam array de dados, criam uma array dinâmica e
//devolvem o endereço.
       double *imp_C;             //array de importância abs de cada critério.
       double *imp_relA[]; //arrays de importância relativa de cada alt
                                  //segundo critério.
};

class Results{
public:
      double *indexA;      //indice de cada alternativa.
      int *idalt;          //num da alternativa (indexA está ordenada)
                                  //logo, posição inicial foi alterada.
};

class Interviewee{
public:
      Data *data;
      Average *avgs;
      Results * ress;
};


//protótipos de funções
Data * getdatafiles();
Interviewee *treat_data(Data *);
bool normalize(double *, int m, int n, int d); //normaliza array de 2 de dimensões
                        //sendo calculada sobre a dimensão 'd'. 'm''n'==M[m][n]
double * average(double *, int m, int n, int d); //== a normalize(), mas calcula média
Interviewee * assize(Interviewee *); //baseada nas médias calcula o index de cada alternativa
                         //e ordena do maior para o menor.
bool order(Results *res, int end);   //ordena do maior para o menor (método bolha)
void gather(double *[],int,int); //junta na memória arrays dispersas 1D em 1 array 2D

void parray(double*, int, int, char*);





int main(){
    Interviewee *res;
    Data *dat;
    char r;



   //Pega dados dos arquivos e aloca internamente
   dat=getdatafiles();



    //Processa completamente os dados e dá resultado final
   res=treat_data(dat);
   if(res==0){
      cout<<"Erro interno inesperado. Dados não puderam ser processados."<<endl;
      cout<<"O programa será encerrado."<<endl;
      system("pause");
      return 0;
   }

    system("pause");
   return 0;
}



Data * getdatafiles(){
   static Data *d;

   d=new Data;
   d->numalt=3;
   d->numcrit=3;

   d->esccrit=3;
   d->escalt=3;


   d->intercrit[0][0]=1;
   d->intercrit[0][1]=2;
   d->intercrit[0][2]=2;
   d->intercrit[1][0]=0,5;
   d->intercrit[1][1]=1;
   d->intercrit[1][2]=2;
   d->intercrit[2][0]=0,5;
   d->intercrit[2][1]=0,5;
   d->intercrit[2][2]=1;



   for(int crit=0; crit<d->numcrit; crit++){
      d->interalt[crit][0][0]=1;
      d->interalt[crit][0][1]=2;
      d->interalt[crit][0][2]=2;
      d->interalt[crit][1][0]=0,5;
      d->interalt[crit][1][1]=1;
      d->interalt[crit][1][2]=2;
      d->interalt[crit][2][0]=0,5;
      d->interalt[crit][2][1]=0,5;
      d->interalt[crit][2][2]=1;
   }


   return d;
}



Interviewee *treat_data(Data * dat){

   static Interviewee* p;

   p=new Interviewee;
   if(p==0)
      return 0;
   p->ress=new Results;
   p->avgs=new Average;

   p->data=dat;


   normalize(p->data->intercrit[0],p->data->numcrit,p->data->numcrit,1);
   parray(p->data->intercrit[0],p->data->numcrit,p->data->numcrit,"intercrit");

   for(int crit=0;crit<p->data->numcrit;crit++){
      normalize(&(p->data->interalt[crit][0][0]),p->data->numalt,p->data->numalt,1);
      parray(&(p->data->interalt[crit][0][0]),p->data->numalt,p->data->numalt,"interalt");
   }

   p->avgs->imp_C = average(p->data->intercrit[0], p->data->numcrit, p->data->numcrit, 2);
   parray(p->data->intercrit[0],p->data->numcrit,p->data->numcrit,"intercrit");
   parray(p->avgs->imp_C,1,p->data->numcrit,"imp_C");

   for(int crit=0;crit<p->data->numcrit;crit++){
      p->avgs->imp_relA[crit] = average(&(p->data->interalt[crit][0][0]), p->data->numalt, p->data->numalt, 2);
      cout<<"crit="<<crit<<endl<<endl<<endl;
   }
   gather(p->avgs->imp_relA, p->data->numcrit, p->data->numalt);
   parray(p->avgs->imp_relA[0],p->data->numcrit,p->data->numalt,"imp_relA");

   p=assize(p);
   parray(p->ress->indexA,1,p->data->numalt,"indexA");

   return p;
}



bool normalize(double *ar, int m, int n, int d){
     double sum=0;


     if(d!=1 && d!=2)
        return false;

     for(int x=0; x<m; x++){
        for(int y=0; y<n; y++){
           if(d==1)
              sum+=*(ar+x+y*n);
           else sum+=*(ar+x*n+y);
        }
        for(int y=0; y<n; y++){
           if(d==1)
              *(ar+x+y*n)/=sum;
           else *(ar+x*n+y)/=sum;
        }
        sum=0;
     }
     return true;
}

double * average(double *ar, const int m, const int n, int d){
     static double *avg1, *avg2;
     double sum=0;

     if(d!=1 && d!=2)
        return 0;


     if(d==1){
        avg1=new double[n];
        for(int x=0; x<m; x++){
           for(int y=0; y<n; y++)
                 sum+=*(ar+x+y*n);
           avg1[x]=sum/m;
           sum=0;
        }
        parray(avg1,1,n,"avg1");
        return avg1;
     }else{
        avg2=new double[m];
        for(int x=0; x<m; x++){
           for(int y=0; y<n; y++)
                 sum+=*(ar+x*n+y);
           avg2[x]=sum/n;
           sum=0;
        }
        parray(avg2,1,m,"avg2");
        return avg2;
     }
}

Interviewee * assize(Interviewee * p){
   int crit, alt;

   p->ress->indexA=new double[p->data->numalt];
   p->ress->idalt=new int[p->data->numalt];


   for(alt=0; alt < p->data->numalt; alt++){
     p->ress->indexA[alt]=0;
     p->ress->idalt[alt]=alt;
     for(crit=0; crit < p->data->numcrit; crit++){
        p->ress->indexA[alt]+= p->avgs->imp_relA[crit][alt] * p->avgs->imp_C[crit];
     }
   }

   if(order(p->ress,p->data->numalt)==false){
      cout<<"Erro para ordenar, verifique o código."<<endl;
      return 0;
   }

   return p;
}

bool order(Results *res, int end){
     bool c=true;
     double aux=0;
     int alt, aux2;

     while(c==true){
        c=false;
        for(alt=0; alt+1<end; alt++){
           if(res->indexA[alt] < res->indexA[alt+1]){
              c=true;
              aux=res->indexA[alt+1];
              res->indexA[alt+1] = res->indexA[alt];
              res->indexA[alt] = aux;
              aux2=res->idalt[alt+1];
              res->idalt[alt+1] = res->idalt[alt];
              res->idalt[alt] = aux2;
           }
        }
        end--;
     }

     return true;
}



void parray(double* a,int m,int n, char* title){  //matriz unidimensional == parray(*,1,n,*);
     cout<<title<<endl;
     for(int x=0;x<m;x++){
        for(int y=0; y<n; y++)
           cout<<*(a+x*n+y)<<"     ";
        cout<<endl;
     }
     cout<<endl<<endl<<endl<<endl;
}

void gather(double *a[],const int q,const  int t){
     double *aux;


     aux=new double[q*t];
     for(int x=0; x<q; x++)
        for(int y=0; y<t; y++)
           *(aux+x*t+y)=*(a[x]+y);

     for(int x=0;x<q; x++){
        delete[] a[x];
        a[x]=aux+x*t;
     }
}

Link para o comentário
Compartilhar em outros sites

1 resposta a esta questão

Posts Recomendados

  • 0

Ok, está parcialmente resolvido.

Reescrevi usando os ponteiros dinâmicos da maneira certa (**, ao invés de *[]) e o problema aparentemente parou. Mas não sei explicar porque a invasão de memória causaria o problema apresentado... de qualquer forma marquei como "resolvido". Valeu a quem ajudou e a quem tentou.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,4k
×
×
  • Criar Novo...