c - Memory leak in realloc

2

I've had a memory leak in a realloc for two days and I can not find the problem.

Here I attach the code:

#include "palabra.h"

Palabra * palabraNueva(){
	Palabra* pal = NULL;

	pal = (Palabra*)malloc(sizeof(Palabra));

	if(pal == NULL){
		printf("Error en la reserva de la palabra\n");
		return NULL;
	}

	pal->tamano = 0;

	pal->contenido = (char**)malloc(sizeof(char*)*pal->tamano);
	if(pal->contenido == NULL){
		printf("Error al reservar memoria a la coleccion de letras\n");
	}

	return pal;
}


void palabraElimina(Palabra * p_p){

    int i;

	if(p_p->tamano != 0 ){
    for(i=0 ; i < p_p->tamano; i++){
        free(p_p->contenido[i]);
    }
	free(p_p->contenido);
	}
    free(p_p);
}

Palabra * palabraInsertaLetra(Palabra * p_p, char * letra){

	int longitud;
	int tam = 0;

	if(letra == NULL){
		printf("Letra vacia, Error\n");
		return NULL;
	}

	longitud = p_p->tamano;

	tam = strlen(letra) + 1;

	p_p->contenido=(char**)realloc(p_p->contenido,sizeof(char*)*(longitud+1));

	p_p->contenido[longitud] = (char*)malloc(sizeof(char)*tam);

	if(p_p->contenido == NULL){
		printf("Error en la reserva de memoria de la copia de la letra\n");
		return NULL;
	}

	strcpy(p_p->contenido[longitud], letra);
	
	p_p->tamano++;

	return p_p;

}

void palabraImprime(FILE * fd, Palabra * p_p){
	int i;

	if(p_p == NULL){
		printf("Palabra a NULL a la hora de imprimir palabra\n");
		return;
	}

	fprintf(fd, "[(%d) ", p_p->tamano);
	for(i=0;i<p_p->tamano;i++){
		if(i==p_p->tamano-1){
			fprintf(fd, "%s ",p_p->contenido[i]);
		} else {
			fprintf(fd, "%s ",p_p->contenido[i]);
		}
	}
	fprintf(fd,"]\n");
	return;
}

int palabraTamano(Palabra * p_p){
	if(p_p == NULL){
		printf("Palabra a NULL a la hora de devolver el tamano de la palabra\n");
		return -1;
	}

	return p_p->tamano;
}

char * palabraQuitaInicio(Palabra * p_p){

	char* letraQuitada;

	if(p_p == NULL){
		printf("Palabra null a la hora de quitar letra\n");
		return NULL;
	}

	letraQuitada = p_p->contenido[0];
	
	p_p->contenido++;
	p_p->tamano--;
	
	return letraQuitada;
}

And here the main of the program:

#include "palabra.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
	Palabra * pal;
	int i;
	char letra [20];
	char * letrai;
	pal = palabraNueva();
	for (i=0; i < argc-1; i++)
	{
		sprintf(letra,"l_%d_%s",i,argv[1+i]);
		palabraInsertaLetra(pal,letra);
		fprintf(stdout,"pal_%d:\n",i);
		palabraImprime(stdout,pal);
		fprintf(stdout,"\n");
	}
	while ( palabraTamano(pal) > 0 )
	{
		fprintf(stdout,
		"QUITAMOS %s DE LA PALABRA QUE QUEDA ASI:\n",letrai=palabraQuitaInicio(pal));
		palabraImprime(stdout,pal);
	free(letrai);
	}
	palabraElimina(pal);
	return 0;
}

The valgrind error is attached here below:

==3097== HEAP SUMMARY:
==3097==     in use at exit: 208 bytes in 1 blocks
==3097==   total heap usage: 54 allocs, 53 frees, 2,996 bytes allocated
==3097== 
==3097== 208 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3097==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3097==    by 0x400B2A: palabraInsertaLetra (palabra.c:51)
==3097==    by 0x4008EB: main (main.c:15)
==3097== 
==3097== LEAK SUMMARY:
==3097==    definitely lost: 208 bytes in 1 blocks
==3097==    indirectly lost: 0 bytes in 0 blocks
==3097==      possibly lost: 0 bytes in 0 blocks
==3097==    still reachable: 0 bytes in 0 blocks
==3097==         suppressed: 0 bytes in 0 blocks
==3097== 
==3097== For counts of detected and suppressed errors, rerun with: -v
==3097== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Thanks in advance!

    
asked by Lexo 07.10.2018 в 10:58
source

1 answer

3

As far as my mathematics is concerned, x * 0 = 0, then this code:

pal->tamano = 0;

pal->contenido = (char**)malloc(sizeof(char*)*pal->tamano);

At first it does not look too good. In the first line initialize pal->tamano to 0 and then calculate the amount of memory to reserve from that value ...

In fact if we look at the documentation in this regard we see that asking malloc 0 bytes is not a good idea:

  

If size is zero, the return value depends on the particular library implementation (it may or may not be a null pointer), but the return pointer shall not be dereferenced.

So, confirmed, that memory reserve is not well made. You should wait for pal->tamano to have a positive value before calling malloc

    
answered by 08.10.2018 / 08:22
source