Jump to content
FMCalisto

[Resolvido] malloc causa sigabrt

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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);

Edited by 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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

  • Vote 1

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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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 ?

Edited by HappyHippyHippo
  • Vote 1

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

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Edited by FMCalisto

Made by Calliboy Rules!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.