Ir ao conteúdo
  • Cadastre-se

C++ Usando ponteiros e alocação dinâmica, mas deu o erro "signal: segmentation...


Astronauta73
Ir à solução Resolvido por arfneto,

Posts recomendados

 

Olá, o que o programa pretende não é a questão, mas por quê da o seguinte erro no programa:  "signal: segmentation fault (core dumped)", na seguinte situação... A princípio o programa vai rodar tranquilamente, desde que a declaração " int **v " esteja, no programa, declarado depois de " int **p", o que não é o caso aqui, pois deixei de forma obrigatória para entender o problema. Mais a fundo, descobri que não precisa ser necessariamente um ponteiro de ponteiro para dar esse problema, ao contrario, pode ser uma variável qualquer com valor definido ou não.

 

Obs: O erro só acontece quando usado alocação dinâmica, independente se a criação é no escopo do main ou numa função, como é o caso aqui.

 

 

#include <iostream>

using namespace std;

int Quest();

void criar (int **p, int x);


int main(){

int **v;

int x=Quest();

int **p;


criar(p,x);


cout<<"\nFunciona !\n";


delete[] *ponteiro;


}


void criar (int **p, int x) {

*p=new int[x];

for(int i=0; i<x; i++){
p[i]= new int[x]; 
}

}


int Quest(){

int q;

cout<<"Digite um valor: ";
cin>>q;

return q;

}

 

 

 

 

  • Amei 1
Link para o comentário
Compartilhar em outros sites

  • Solução

Não consigo entender o que iria funcionar aqui. Não entendi o propósito do programa e não há razão para se programar assim, em C ou C++.

 

        cout << "\nFunciona !\n";

 

Isso só mostraria que o programa não cancelou ainda. E que compilou ok. Não serve como um teste.

 

O que é ponteiro?

 

    delete[] * ponteiro;

 

Há muitos anos, desde C++11 não há razão para escrever assim em C++. E mesmo em C++98 esse delete deveria estar em um destrutor e nunca solto pelo programa.

 

int main()
{
    int** v;
    int x = Quest();
    int** p;
    criar(p, x);
    cout << "\nFunciona !\n";
    delete[] * ponteiro;
}

 

já perguntei sobre ponteiro... e v seria o que? não foi alocado e jamais foi usado.

 

E Quest() serve apenas para ler um número então o que muda no programa em relação a escrever
 

    int x = 42;


e seguir com seja lá o que for que o programa faz?

 

Ao que parece cria()

 

void criar(int** p, int x)
{
    *p = new int[x];
    for (int i = 0; i < x; i++) { p[i] = new int[x]; }
}

 

apenas cria um vetor de tamanho x, o valor que foi lido por Quest(). Só que depois aloca um vetor de x int para cada posição de *p. Só que *p é int[] e não um ponteiro. Uma confusão. 

 

E acho que está mesmo errado.

 

E ainda retorna void, um outro erro nesse caso.

 

O que pretende criar com cria() ? porque retorna void? Porque está usando C++ e escrevendo C?

 

Não está claro que cria() é um construtor????

 

Se  cria(int**  p,  int x )  deveria criar em p um vetor de x vetores para int

 

Escrever assim só complica as coisas. Muito. Porque void se vai criar alocando? Não retorne void nunca. Isso se eu entendi o que quer que "funcione" aqui. Vou te mostrar dois exemplos considerando isso. Se não for assim acho que não vai ter dificuldade em adaptar para seu caso. Ou perguntar de novo.

 

Pode escrever 
 

    int** criar(int x);

 

E usar 
 

    int** p = criar(x);

 

Que é bem mais simples eu acho.

 

Mas entenda que
 

Citação

 

se p é **int então *p é int*


 

 

e só de ver isso não dá pra saber que *p é um ponteiro para um int ou um vetor.

 

Citação

Um vetor é um ponteiro mas um ponteiro não é um vetor necessariamente.

 

Então se quer criar um vetor de vetores para int de tamanho x precisa de fato criar isso. Imagine que  vai criar um vetor de x vetores para vetores de x int. Precisa saber se de fato criou isso. Não basta escrever "funciona". Eis um exemplo:

 

Imagine então que os valores em cada vetor serão assim, para x = 4

  • cria() vai retornar 4 vetores de ponteiros para int
  • cada um desses vai ser um vetor de 4 int
  • e eles vão valer
    • para p[0] 0,1,2,3
    • para p[1] 10,11,12,13
    • para p[2] 20,21,22,23
    • para p[3] 30,31,32,33

Assim pode listar isso depois de chamar cria() e ver se deu certo porque já sabe os valores que tem que mostrar, certo? Espero que tenha dado para entender porque não basta escrever "funciona".

 

E depois de criar tem que apagar todo mundo na ordem inversa ou seu programar pode cancelar no final, porque TEM que liberar tudo que alocou...

 

Um exemplo em C++,  no modo C dos anos 80

 

int** apagar(int**,int);
int** criar(int x);
int   mostrar(int**,int);

 

O jeito comum de fazer em C, uma função cria o vetor, uma apaga e outra mostra. Quest() não é relevante aqui. Não há razão para escrever um programa interativo.

 

Essa versão de cria() usa o exemplo acima e preenche todas as posições de todos os vetores com valores conhecidos assim pode conferir facilmente:
 

int** criar(int x)
{
    int** p = new int*[x];
    for (int i = 0; i < x; i+=1)
    { 
        p[i] = new int[x];
        for ( int j = 0; j<x; j+=1 ) p[i][j] = 10*i + j;
    }
    return p;
}

 

Essa versão de apagar() apaga tudo na ordem certa
 

int** apagar(int** p, int x)
{
    for (int i = 0; i < x; i+=1) delete[] p[i];
    delete[] p;
    return nullptr;
}

 

Note que usando apagar assim permite que se invalide o ponteiro no chamador, o que é um seguro contra esquecer que apagou e usar o ponteiro em outro lugar...

 

Um exemplo completo
 

#include <iostream>
using namespace std;

int** apagar(int**,int);
int** criar(int x);
int   mostrar(int**,int);

int main()
{
    int   x = 8;
    int** p = criar(x);
    cout << "\nFunciona! x = " << x << "\n";
    int res = mostrar(p,x);
    cout << "mostrar() listou " << res << " elementos\n";
    cout << "apagando tudo...\n";
    p = apagar(p,x);
    return 0;
}

int** apagar(int** p, int x)
{
    for (int i = 0; i < x; i+=1) delete[] p[i];
    delete[] p;
    return nullptr;
}

int** criar(int x)
{
    int** p = new int*[x];
    for (int i = 0; i < x; i+=1)
    { 
        p[i] = new int[x];
        for ( int j = 0; j<x; j+=1 ) p[i][j] = 10*i + j;
    }
    return p;
}

int   mostrar(int** v, int d)
{
    int n = 0;
    for (int i = 0; i < d; i+=1)
    { 
        cout << "[" << i << "] ";
        for ( int j = 0; j<d; j+=1 ) n+=1, cout << v[i][j] << " ";
        cout << "\n";
    }
    cout << "\n";
    return n;  
};

 

A saída
 


Funciona! x = 8
[0] 0 1 2 3 4 5 6 7
[1] 10 11 12 13 14 15 16 17
[2] 20 21 22 23 24 25 26 27
[3] 30 31 32 33 34 35 36 37
[4] 40 41 42 43 44 45 46 47
[5] 50 51 52 53 54 55 56 57 
[6] 60 61 62 63 64 65 66 67
[7] 70 71 72 73 74 75 76 77

Listados 64 elementos

Apagando...

 

Claro que mostra() não precisava retornar nada, mas retornar o total de elementos dá mais uma segurança, já que deve ser claro x*x.

Um modo comum de fazer isso, desta vez em C++ 2011

 

v_int_int é a struct com os vetores de vetores de int. main() pode ser bem simples:

 

int main(void)
{
    v_int_int teste(8);
    cout << teste;
};

 

E o código é o mesmo praticamente. Só que em C++ é mais fácil de escrever e ler. Redefinir << é algo comum para uma struct em C++ porque assim pode usar cout << struct e escrever como quiser sem ter que ficar formatando em toda parte ou escrever uma função, o que seria a mesma coisa só que mais difícil de ler

 

criar() é simplesmente construir uma struct dessas. apagar() é o destrutor, com o til na frente. mostrar é o tal << e a vida segue.

 

O exemplo completo
 

#include <iostream>
using namespace std;

struct v_int_int
{
    int   x;
    int** p;
    v_int_int(int);
    ~v_int_int();
};

ostream& operator<<(ostream& out, v_int_int& c);

int main(void)
{
    v_int_int teste(8);
    cout << teste;
};

v_int_int::~v_int_int()
{
    cout << "\nApagando";
    for (int i = 0; i < x; i+=1) delete[] p[i];
    delete[] p;
    cout << "...\n";
}

v_int_int::v_int_int(int tamanho) : x(tamanho)
{
    cout << "\nFunciona! x = " << x << "\n";
    p = new int*[x];
    for (int i = 0; i < x; i+=1)
    { 
        p[i] = new int[x];
        for ( int j = 0; j<x; j+=1 ) p[i][j] = 10*i + j;
    }
}

ostream& operator<<(ostream& out, v_int_int& c)
{
    int n = 0;
    for (int i = 0; i < c.x; i+=1)
    { 
        out << "[" << i << "] ";
        for ( int j = 0; j<c.x; j+=1 ) n+=1, cout << c.p[i][j] << " ";
        out << "\n";
    }
    out << "\nListados " << n << " elementos\n";
    return out;  
};

 

A saída é a mesma.

 

No geral não é mais preciso alocar e liberar memória assim em C++, mas agora não posso escrever outro exemplo

 

 

 

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@arfneto agradeço pelo seu tempo, estou aprendendo ainda, como você pode ver... O código em si, como eu havia dito, não importava o que ele fazia, pois ele era de uma pequena parte do código, eu só o reduzi na raiz do problema, a qual eu ainda não sei, mas com a sua ajuda consegui resolver uma situação futura e melhorar o código, muito obrigado. 

 

11 horas atrás, arfneto disse:

Isso só mostraria que o programa não cancelou ainda. E que compilou ok. Não serve como um teste.

 

Compilando no Replit, esse programa que compilou para você, não compilou para mim, por isso levantei a minha dúvida aqui. Mas mais uma vez, obrigado pela atenção, foi de grande ajuda. 

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

57 minutos atrás, Astronauta73 disse:

Compilando no Replit, esse programa que compilou para você, não compilou para mim, por isso levantei a minha dúvida aqui

 

Não entendi.  Se fala do código que postou, não há como compilar ok. Tem muitos erros. ponteiro não está declarado, v não é usado, criar() usa um valor não inicializado. Sugiro fazer na linha do que eu mostrei em C++, ou escrever em C.

 

59 minutos atrás, Astronauta73 disse:

eu só o reduzi na raiz do problema, a qual eu ainda não sei

 

Talvez deva postar então o problema em si...

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Acredito que queira criar um array dinâmico dentro de uma função certo?

#include <iostream>

using namespace std;

int Quest();

void criar (int *&p, int x);


int main(){

int x=Quest();

int *p;


criar(p,x);

for(int i=0; i<x; i++){
    cout << p[i] << endl;
}


cout<<"\nFunciona !\n";


delete[] p;


return 0;
}


void criar (int *&p, int x) {


p = new int[x];

for(int i=0; i<x; i++){
p[i]= x; 
}
}


int Quest(){

int q;

cout<<"Digite um valor: ";
cin>>q;

return q;

}

Ou:

 

 

#include <iostream>

using namespace std;

int Quest();

void criar (int **p, int x);


int main(){

int x=Quest();

int *p;


criar(&p,x);

for(int i=0; i<x; i++){
    cout << p[i] << endl;
}


cout<<"\nFunciona !\n";


delete[] p;


return 0;
}


void criar (int **p, int x) {


*p = new int[x];

for(int i=0; i<x; i++){
(*p)[i]= x; 
}
}


int Quest(){

int q;

cout<<"Digite um valor: ";
cin>>q;

return q;

}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...