Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #59 da revista programar. Faz já o download aqui!

FMCalisto

[Resolvido] malloc causa sigabrt

Mensagens Recomendadas

FMCalisto    0
FMCalisto

Bom dia,

Quando tentamos alocar o nó da segunda palavra que queremos meter numa arvore (i.e. alocar para head->left ou right):

n = (struct node*) malloc (sizeof(struct node));
i = (struct Word*) malloc (sizeof (struct Word));
i->word = (char*) malloc(sizeof(char)*(strlen(palavra)+1));

Desta forma origina um sigabrt, onde nos é desconhecida a origem deste erro.

Com os melhores cumprimentos.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    96
pmg

Suspeito que o problema esteja em "palavra" e o SIGABRT venha da tentativa de seguir um NULL pointer.

n = (struct node*) malloc (sizeof(struct node));
i = (struct Word*) malloc (sizeof (struct Word));
fprintf(stderr, "DEBUG: palavra aponta para %p\n", (void*)palavra); /* DEBUG */
i->word = (char*) malloc(sizeof(char)*(strlen(palavra)+1));

sizeof(char) é, por definição, 1 e pode ser removido da multiplicação; os casts são, quando muito, redundantes e podem esconder um erro que o compilador apanharia sem os casts: assim

n = malloc(sizeof *n);
i = malloc(sizeof *i);
fprintf(stderr, "DEBUG: palavra aponta para %p\n", (void*)palavra); /* DEBUG */
i->word = malloc(strlen(palavra) + 1);

Editado por pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Obrigado pmg,

no entanto testamos e não é um problema da palavra visto quando aplicado o fprintf este devolve posições de memória diferentes de NULL. Além disso, temos a certeza de que o palavra é inicializado, pois este é um argumento da função onde o código acima está inserido.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    96
pmg

Então só pode ser por o malloc devolver NULL.

n = malloc(sizeof *n);
if (!n) fprintf(stderr, "sem memoria para novo objecto (n)\n");
i = malloc(sizeof *i);
if (!i) fprintf(stderr, "sem memoria para novo objecto (i)\n");
i->word = malloc(strlen(palavra) + 1);
if (!i->word) fprintf(stderr, "sem memoria para novo objecto (i->word)\n");

ou então o SIGABRT não está directamente relacionado com o código apresentado.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Então só pode ser por o malloc devolver NULL.

n = malloc(sizeof *n);
if (!n) fprintf(stderr, "sem memoria para novo objecto (n)\n");
i = malloc(sizeof *i);
if (!i) fprintf(stderr, "sem memoria para novo objecto (i)\n");
i->word = malloc(strlen(palavra) + 1);
if (!i->word) fprintf(stderr, "sem memoria para novo objecto (i->word)\n");

ou então o SIGABRT não está directamente relacionado com o código apresentado.

Pois estamos desconfiados que seja Sistema Operativo, visto em Linux originar sigabrt e em Windows originar apenas segmentation fault.

Cumprimentos.

Fica aqui o Source Code do nosso ficheiro Tree.c:

#include <string.h>
#include <stdlib.h>
#include "Constants.h"
#include "FuncDef.h"
#include "Tree.h"
struct node* addToTree(char* palavra, int line, struct node* tree) {
   struct node* n;
   struct Word* i;
   int index = 0, old_index;
   int* aux = NULL;
   if (tree == NULL)
   {
    n = (struct node*) malloc (sizeof(struct node));
    i = (struct Word*) malloc (sizeof (struct Word));
    i->word = (char*) malloc(sizeof(char)*(strlen(palavra)+1));
    strcpy(i->word, palavra);
    i->counter = 1;
    i->forgotten = 0;
    i->lines = (int*) malloc (sizeof (char)*INIT_SIZE_LINES);
    for (index = 0; index < INIT_SIZE_LINES; index++)
	    i->lines[index] = 0;
    i->lines[0] = line+1;
    i->actual_max_size_lines = INIT_SIZE_LINES;
    n->item = i;
    n->left = n->right = NULL;
    tree = n;
   }
   else if (strcmp(palavra, Key(tree->item)) < 0)
   {
    addToTree(palavra, line, tree->left);
   }
   else if (strcmp(palavra, Key(tree->item)) > 0)
    addToTree(palavra, line, tree->right);
   else
   {
    (tree->item->counter)++;
    /*percorre vector ate encontrar a primeira posicao livre*/
    for (old_index = 0; index < tree->item->actual_max_size_lines; index++)
    {
	    if (tree->item->lines[index] == 0)
			 break;
    }
    /* se a linha onde estou for diferente da ultima que coloquei*/
    if (line != tree->item->lines[index])
    {
	    /*se cheguei ao ultimo indice e o seu conteudo nao for zero, o vector esta cheio */
	    if (old_index == tree->item->actual_max_size_lines && tree->item->lines[index] != 0)
	    {
		    aux = (int*) realloc(tree->item->lines, 2*tree->item->actual_max_size_lines);
		    tree->item->lines = aux;
		    for (index = tree->item->actual_max_size_lines;index < tree->item->actual_max_size_lines*2; index++)
			    tree->item->lines[index] = 0;
		    tree->item->actual_max_size_lines *= 2;
		    tree->item->lines[old_index+1] = line;
	    }
	    else tree->item->lines[old_index] = line;
    }
   }
   return tree;
}
struct Word* searchInTree(char* key, struct node* tree) {
   if (tree == NULL)
    return NULL;
   else if (strcmp(key, Key(tree->item)) < 0)
    searchInTree(key, tree->left);
   else if (strcmp(key, Key(tree->item)) > 0)
    searchInTree(key, tree->right);
   else
    return tree->item;
   return NULL;
}

void traverse (struct node* tree, void (*visit)(struct node* tree), int order) {
   if (tree == NULL)
    return;
   switch (order) {
    case PRE_ORDER:
	    (*visit)(tree);
	    traverse(tree->left, visit, order);
	    traverse(tree->right, visit, order);
	    break;
    case IN_ORDER:
	    traverse(tree->left, visit, order);
	    (*visit)(tree);
	    traverse(tree->right, visit, order);
	    break;
    case POST_ORDER:
	    traverse(tree->left, visit, order);
	    traverse(tree->right, visit, order);
	    (*visit)(tree);
	    break;
   }
}


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    96
pmg

Como é que chamas addToTree()?

addToTree("palavra", 42, myTree);
/* ou */
myTree = addToTree("palavra", 42, myTree);


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Como é que chamas addToTree()?

addToTree("palavra", 42, myTree);
/* ou */
myTree = addToTree("palavra", 42, myTree);

addToTree() é chamado da seguinte forma:

tree = addToTree(palavra, i, tree);

Cumprimentos.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    96
pmg

Dentro da função, recursivamente, não usas a forma correcta de chamar a função!

   else if (strcmp(palavra, Key(tree->item)) < 0)
   {
           tree->left = addToTree(palavra, line, tree->left); /* assign to tree->left */
   }
   else if (strcmp(palavra, Key(tree->item)) > 0)
           tree->right = addToTree(palavra, line, tree->right); /* assign to tree->right */

Sugiro que alteres a função addToTree() para

int addToTree(const char *palavra, int line, struct node **tree);

onde o valor devolvido indoca se correu tudo bem (com 0) ou se houve erro (1, 2, 3, ..., -1, -2, ...)

e o parametro tree passa a ser um ponteiro para um ponteiro e portanto podes alterar o valor dentro da função que chama esta


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Dentro da função, recursivamente, não usas a forma correcta de chamar a função!

   else if (strcmp(palavra, Key(tree->item)) < 0)
{
		tree->left = addToTree(palavra, line, tree->left); /* assign to tree->left */
}
else if (strcmp(palavra, Key(tree->item)) > 0)
		tree->right = addToTree(palavra, line, tree->right); /* assign to tree->right */

Sugiro que alteres a função addToTree() para

int addToTree(const char *palavra, int line, struct node **tree);

onde o valor devolvido indoca se correu tudo bem (com 0) ou se houve erro (1, 2, 3, ..., -1, -2, ...)

e o parametro tree passa a ser um ponteiro para um ponteiro e portanto podes alterar o valor dentro da função que chama esta

Dizes-me que é para por o addToTree a retornar um inteiro, mas depois queres associar o tree->right que é um ponteiro ao resultado de addToTree que é um inteiro e isso não pode funcionar, certo?

Obrigado e cumprimentos.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Source Code do Tree.h:

#ifndef Parser_Tree_h
#define Parser_Tree_h
#include "FuncDef.h"
struct node {
   struct Word* item;
   struct node* left;
   struct node* right;
};
struct node* addToTree (char* word, int line, struct node* tree);
struct Word* searchInTree(char* key, struct node* tree);
void traverse (struct node* tree, void (*visit)(struct node* tree), int order);
#endif

Estou com algum receio que a chamada dos protótipos origine algum tio de erro.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1140
HappyHippyHippo

Dizes-me que é para por o addToTree a retornar um inteiro, mas depois queres associar o tree->right que é um ponteiro ao resultado de addToTree que é um inteiro e isso não pode funcionar, certo?

Obrigado e cumprimentos.

olha para o protótipo da função e como deve ser chamada :

int addToTree(const char *palavra,
             int line,
             struct node **tree);

if (addToTree(palavra,
             line,
             &(tree->left)) != 0) // <-- referência do ponteiro do ramo a ser atribuido
{
 // erro ...
}

---------

já agora: porque ?

struct node {
   struct Word* item; // ponteiro
   struct node* left;
   struct node* right;
};

e não

struct node {
   struct Word item; // <--- estrutura
   struct node* left;
   struct node* right;
};

visto que existe sempre uma relação 1:1 entre as duas estruturas, só isso simplifica o código e previne erros

----

pss : só uma questão final = não consegues passar isso por um debugger e ver em que linha a excepção está a ser originada ?

Editado por HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    96
pmg

Dizes-me que é para por o addToTree a retornar um inteiro, mas depois queres associar o tree->right que é um ponteiro ao resultado de addToTree que é um inteiro e isso não pode funcionar, certo?

É claro que mudando a função tens que mudar o código que usa a função! Esqueci-me de referir esse pormenor :)


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Word é uma estrutura que está definida:

typedef struct node* node;
struct Word{
   char* word;
   int counter;
   int* lines;
   int forgotten;
   int actual_max_size_lines;
};

Cumprimentos.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Já agora o programa executado em Linux origina o seguinte Warning:

warning: GDB: Failed to set controlling terminal: Operation not permitted

Estamos a correr em Linux Debian.

Cumprimentos.


Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1140
HappyHippyHippo

Já agora o programa executado em Linux origina o seguinte Warning:

warning: GDB: Failed to set controlling terminal: Operation not permitted

Estamos a correr em Linux Debian.

Cumprimentos.

verifica se estas soluções te resolvem o problema :

http://forums.netbeans.org/topic15797.html


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
FMCalisto    0
FMCalisto

Obrigado pela ajuda,

Deixo aqui uma solução elegante que ficará para eventuais discussões.

Ficheiro Tree.c: (incompleto)

#include <string.h>
#include <stdlib.h>
#include "Constants.h"
#include "FuncDef.h"
#include "Tree.h"
struct node* addToTree(char* palavra, int line, struct node* tree, struct node* pai_tree, struct node* raiz, int flag) {
/*struct node* n;
struct Word* i;*/
int index = 0, old_index;
int* aux = NULL;
if (tree == NULL)
{
	/*n = NULL;  novo
	i = NULL;*/
	struct node* n = (struct node*) malloc (sizeof(struct node));
	struct Word* i = (struct Word*) malloc (sizeof (struct Word));
	i->word = (char*) malloc(sizeof(char)*(strlen(palavra)+1));
	strcpy(i->word, palavra);
	i->counter = 1;
	i->forgotten = 0;
	i->lines = (int*) malloc (sizeof (int)*INIT_SIZE_LINES); /* ver char para int*/
	for (index = 0; index < INIT_SIZE_LINES; index++)
		i->lines[index] = 0;
	i->lines[0] = line+1;
	i->actual_max_size_lines = INIT_SIZE_LINES;
	n->item = i;
	n->left = n->right = NULL;
	tree = n;
	if (raiz == NULL)
		raiz = tree;
	if (flag != -1 && tree != raiz)
	{   if (flag == 0)
			pai_tree->left = tree;
		else
			pai_tree->right = tree;
	}
	n = NULL;
	i = NULL;
}
else if (strcmp(palavra, Key(tree->item)) < 0)
	addToTree(palavra, line, tree->left, tree, raiz, 0);
else if (strcmp(palavra, Key(tree->item)) > 0)
	addToTree(palavra, line, tree->right, tree, raiz, 1);
else
{
	(tree->item->counter)++;
	/*percorre vector ate encontrar a primeira posicao livre*/
	for (old_index = 0; index < tree->item->actual_max_size_lines; index++)
	{
		if (tree->item->lines[index] == 0)
			 break;
	}
	/* se a linha onde estou for diferente da ultima que coloquei*/
	if (line != tree->item->lines[index])
	{
		/*se cheguei ao ultimo indice e o seu conteudo nao for zero, o vector esta cheio */
		if (old_index == tree->item->actual_max_size_lines && tree->item->lines[index] != 0)
		{
			aux = (int*) realloc(tree->item->lines, 2*tree->item->actual_max_size_lines);
			tree->item->lines = aux;
			for (index = tree->item->actual_max_size_lines;index < tree->item->actual_max_size_lines*2; index++)
				tree->item->lines[index] = 0;
			tree->item->actual_max_size_lines *= 2;
			tree->item->lines[old_index+1] = line;
		}
		else tree->item->lines[old_index] = line;
	}
}
return tree;
}
struct Word* searchInTree(char* key, struct node* tree) {
if (tree == NULL)
	return NULL;
else if (strcmp(key, Key(tree->item)) < 0)
	searchInTree(key, tree->left);
else if (strcmp(key, Key(tree->item)) > 0)
	searchInTree(key, tree->right);
else
	return tree->item;
return NULL; /* caso de mau resultado*/
}

void traverse (struct node* tree, void (*visit)(struct node* tree), int order) {
if (tree == NULL)
	return;
switch (order) {
	case PRE_ORDER:
		(*visit)(tree);
		traverse(tree->left, visit, order);
		traverse(tree->right, visit, order);
		break;
	case IN_ORDER:
		traverse(tree->left, visit, order);
		(*visit)(tree);
		traverse(tree->right, visit, order);
		break;
	case POST_ORDER:
		traverse(tree->left, visit, order);
		traverse(tree->right, visit, order);
		(*visit)(tree);
		break;
}
}

Ficheiro Tree.h: (incompleto)

#ifndef Parser_Tree_h
#define Parser_Tree_h
#include "FuncDef.h"
struct node {
struct Word* item;
struct node* left;
struct node* right;
};
struct node* addToTree (char* word, int line, struct node* tree, struct node* pai_tree, struct node* raiz, int flag);
struct Word* searchInTree(char* key, struct node* tree);
void traverse (struct node* tree, void (*visit)(struct node* tree), int order);
#endif

Aviso que ambos os ficheiros estão incompletos estando a sua solução ainda por acabar.

Mais uma vez aproveito para agradecer.

Com os melhores cumprimentos.

Editado por FMCalisto

Made by Calliboy Rules!

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora


×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.