paulo1205
(usa Ubuntu)
Enviado em 06/03/2013 - 12:22h
gokernel escreveu:
@paulo: "Exemplo buguento, por sinal."
Ja que começou, seja direto e mostre o suposto BUG .
Eu mostrei, sim: citei literalmente a linha com problema, disse qual é o problema e mostrei uma forma correta de fazer a realocação, que conta com a possibilidade de a chamada a
realloc() falhar, sem, contudo, perder os dados anteriores.
Se você precisa de uma fonte externa para confirmar o que eu disse, veja, por exemplo, <http://www.freebsd.org/cgi/man.cgi?query=realloc&apropos=0&sektion=0&manpath=NetBSD+6.0&arch=default&format=html>. Trata-se da documentação on-line sobre as funções de alocação de memória (
malloc(),
calloc(),
realloc() e
free()), dando dicas valiosas sobre boas práticas para uso seguro dessas funções.
@paulo: "Não olhei o resto do código do seu exemplo"
Como assim, o meu codigo é pequeno ???
AFF, ta querendo "comprar" briga e fugir ao mesmo tempo ? ;).
Não tem briga alguma. Muito menos fuga.
Como você se propôs a ensinar o autor do tópico a fazer alocação dinâmica, o importante era criticar o inegável
bug na forma como foi usada a função
realloc(), que era justamente o assunto de que você estava tratando. Outros aspectos possivelmente problemáticos do programa não me interessavam porque estavam fora do assunto central, e talvez também não fossem objeto de dúvidas aparentes do autor original do tópico.
Mas há ainda outro motivo, muito mais prosaico, para não ter examinado antes o restante do seu código: eu tinha hora marcada para consulta de fisioterapia. E, mesmo depois da tal consulta, também não pude responder ontem à noite, pois o temporal que caiu aqui no Rio de Janeiro me deixou algumas horas ilhado no consultório da fisioterapeuta, e eu cheguei em casa muito tarde, e muito cansado.
Meu objetivo neste fórum não é ser um "chato". Não ganho nada em ficar corrigindo alguém, e não sou fanático por ficar enchendo meu próprio ego. Como disse antes, apontar o erro do seu exemplo foi no sentido de desviar o orientado de uma prática errônea, e quiçá ajudar você mesmo a adotar uma prática melhor nos programas que você vier a fazer.
Mas, já que você mesmo pediu, há, sim, outros problemas naquele seu programa, com os quais eu não tinha me preocupado anteriormente, a saber:
* Outra ocorrência do mesmo problema já apontado: Assim como
realloc(),
strdup(), que chama
malloc() internamente, também pode falhar por falta de memória, devolvendo um ponteiro nulo. Só que você não considera essa possibilidade, e adiciona esse elemento incondicionalmente no array apontado por
pessoa.
* Falta de generalidade: A própria função
strdup() não faz parte do padrão da linguagem C, sendo obrigatória somente no mundo UNIX/POSIX. Outras pessoas podem usar, no Windows ou outra plataforma não-POSIX, compiladores C aderentes ao padrão da linguagem e da biblioteca padrão, nos quais, no entanto, a função
strdup() pode não estar disponível.
* Níveis demais e desnecessários de indireção: Por que fazer
pessoa ser um ponteiro para ponteiro para
Tdata, se o uso que você faz dela é somente como ponteiro para um array que cresce dinamicamente, que poderia ser totalemnte tratado apenas com um nível de ponteiro (i.e. o tipo de
pessoa poderia conformavelmente ser
Tdata*, em vez de
Tdata**)?
* Tipo inapropriado de argumento de função: O tipo do primeiro argumento da função
novo_cadastro() poderia confortavelmente ser
const char*, pois você não altera, dentro da função, os dados apontados pelo argumento. Essa pequena e aparentemente boba mudança permitiria que o seu pequeno programa pudesse ser compilado também como um programa em C++, já que este obriga a compatibilidade de tipos ao usar uma constante literal string (como
"Joao", por exemplo) como argumento de função. (Note que, mesmo em C, o tipo inferido internamente de uma constante literal string é
const char*, mas a linguagem tolera atribuir essas constantes a ponteiros não contantes por uma questão de compatibilidade com código muito antigo, da época em que a linguagem não possuía a palavra-chave
const (ou seja há 24 anos atrás). A meu ver, essa foi uma escolha errada do comitê de padronização do C.)
* Nomes inadequados: O nome da variável
pessoa não me parece adequdo, já que não designa uma pessoa, mas um array de várias pessoas. De carona, segue o nome de
pessoa_len, que, além de não estar ligado a uma pessoa, também não designa um comprimento (
length, de onde suponho vir o "
len"), mas uma quantidade de elementos. Ainda:
Tdata é um nome muito genérico e pouco descrito do dado referenciado, aceitável apenas num programa muito simples (como é o caso), mas jamais num de maior porte.