Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sileno De Oliveira Brito

Problemas com vetor de char em c

Recommended Posts

Quero saber se há algum erro na função testToString eu não estou conseguindo visualizar.

 

Trecho adaptado do código

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* 
*/

#define BUFFER_LITLE 1024
typedef struct _LinkedListNode LinkedListNode;
typedef struct _Pessoa Pessoa;
typedef char * String;
typedef void * Generic;

struct _LinkedListNode {
   Generic content;
   LinkedListNode* next;
};

struct _Pessoa {
   String nome;
   int idade;
};

String pessoaToString(Generic a) {
   String cache = NULL;
   Pessoa *p = (Pessoa *) a;
   int length = 0;

   if (p == NULL) return NULL;
   length = sizeof (*cache) * 256
           cache = (String) malloc(length);
   memset(cache, '\0', length);

   sprintf(cache, "Pessoa: Nome=\"%s\", Idade=\"%d\"\n", p->nome, p->idade);
   return cache;
}

String testToString(LinkedListNode n, String(*toString)(Generic)) {
   String cache = NULL;
   String v1 = NULL;
   String v2 = NULL;
   int length = BUFFER_LITLE;

   if (n == NULL || toString == NULL) return NULL;

   if ((v1 = testToString(n->next, toString)) != NULL) {
       length += (strlen(v1) + 1);
   }

   if ((cache = (String) malloc((sizeof *cache) * length)) == NULL) {
       perror("malloc");
       if (v1 != NULL) {
           free(v1);
       }
       return NULL;
   }
   memset(cache, '\0', length);
   v2 = toString(n->content);

   if (v1 != NULL) strncat(cache, v1, (length - BUFFER_LITLE));
   if (v2 != NULL) strcat(cache, v2);


   if (v1 != NULL) free(v1);
   if (v2 != NULL) free(v2);

   return cache;
}

int main(int argc, char** argv) {

   LinkedListNode l = NULL;
/*
* Supondo que já exista uns 3000 LinkedListNode l
* e que cada LinkedListNode->content tenha um "Pessoa *"
*/
   fprintf(stdout, "%s", testToString(l, pessoaToString));
   return (EXIT_SUCCESS);
}

 

Estou com o seguinte problema: O programa está terminando com SIGABRT exatamente nessa função, está dando erro em strlen(Invalid read of size 1) e erro no strncat (Invalid read of size 1) quando eu uso o valgrind.

 

Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado por postar usando as recomendações que fazemos.

 

A primeira coisa a fazer é retirar os typedefs que escondem ponteiros. Embora isso em si não seja um erro de programação, é um erro de design. Não vale a pena assumir a responsabilidade de lembrar-se que String e Generic são ponteiros (ou ponteiros para ponteiros, etc). É uma enorme fonte de erros.

 

Sugiro que use o fato de que sizeof (char) == 1:

 

char *p = malloc(4);
strcpy(p, "abc");

 

Mais uma sugestão: não faça casting de (void *) para (foo *). A conversão é padrão, automática e usual em C.

 

Por favor, faça estes ajustes.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado por postar usando as recomendações que fazemos.

 

A primeira coisa a fazer é retirar os typedefs que escondem ponteiros. Embora isso em si não seja um erro de programação, é um erro de design. Não vale a pena assumir a responsabilidade de lembrar-se que String e Generic são ponteiros (ou ponteiros para ponteiros, etc). É uma enorme fonte de erros.

 

Sugiro que use o fato de que sizeof (char) == 1:

 

char *p = malloc(4);
strcpy(p, "abc");

 

Mais uma sugestão: não faça casting de (void *) para (foo *). A conversão é padrão, automática e usual em C.

 

Por favor, faça estes ajustes.

 

 

Agradeço, pela dica em relação ao modelo de código, mas o fato de eu usar o typedef de um vetor de char para String me facilita internamente na hora de usar o meu código para ser analisado por ferramentas internas. Salvo os problemas de erros de designer, eu gostaria de saber se a lógica, usada na função testToString para eu obter toda as estruturas de dados presentes na lista encadeada contém algum erro e em relação ao typedef Generic para mim ele é útil ao mudar do ponteiro de void para outra estrutura de dados qualquer, mas se realmente achar necessário eu alterar isso para ter uma visualização mais fácil, não tem problema eu posto já com as modificações. O meu foco todo está na testToString e o modo como ela exibe as estruturas de dados presentes na variável content. O restante é mera ilustração para facilitar o entendimento do problema.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Resolvido, com base na função passada para gerar a "String", não há problemas, mas se a função para gerar a String tiver um tamanho de buffer variado e esse buffer, como era o meu caso, chega um dado momento que o buffer é estourado (O buffer em um dado momento era maior do que o valor que eu tinha reservado) a e assim gera uma violação de endereço e o tal SIGABRT, com essa modificação no código eu consegui acabar com o erro e resolvi o meu problema aqui, mas Obrigado pela ajuda. To postando o código com a solução que eu achei.

 

String testToString(LinkedListNode n, String(*toString)(Generic)) {
   String cache = NULL;
   String v1 = NULL;
   String v2 = NULL;
   int length = 1;
   int v1Length = 0;
   int v2Length = 0;

   if (n == NULL || toString == NULL) return NULL;

   if ((v1 = testToString(n->next, toString)) != NULL) v1Length = strlen(v1);
   if ((v2 = toString(n->content)) != NULL) v2Length = strlen(v2);

   length += v1Length;
   length += v2Length;

   if ((cache = (String) malloc((sizeof *cache) * length)) == NULL) {
       perror("malloc");
       if (v1 != NULL) free(v1);
       if (v2 != NULL) free(v2);
       return NULL;
   }
   memset(cache, '\0', length);

   if (v1 != NULL) strncat(cache, v1, v1Length);
   if (v2 != NULL) strncat(cache, v2, v2Length);

   if (v1 != NULL) free(v1);
   if (v2 != NULL) free(v2);

   return cache;
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Há mais um problema:

 

if (n == NULL || toString == NULL) return NULL;

 

Você encarou 'LinkedListNode' como um tipo de ponteiro. A comparação não faz sentido para a struct.

 

É exatamente este tipo de confusão ao qual me refiro.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Perdão, houve realmente um erro, pois esse não é o código original é um trecho adaptado para exemplificar o meu problema, o erro foi mesmo de transcrissão minha.

No trecho original LinkedListNode é typedef struct _LinkedListNode *LinkedListNode, isso pq a struct orginal no código original somente é criado em por uma função do tipo newLinkedListNode() que retorna struct _LinkedListNode * e cada função new<Struct> tem a sua respectvida free<Struct>(Generic ), e dependendo do caso toString<Struct>(Generic) e compare<Struct>(Generic, Generic). Assim como pessoa typedef struct _Pessoa *Pessoa; onde struct _Pessoa * newPessoa() // alloca os dados e inicializa a struct pesssoa e freePessoa(Generic) recebe pessoa e libera todos os demais ponteiros que existirem na struct _Pessoa.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.