Data passing from one pointer to another

4

In my program you have to create a duplicate function that receives a string and returns a pointer to a new string that is the copy of the previous one. My program "works" the problem is that if the initial string passed as an argument to my duplicate function I define it dynamically, when I release that memory my "copy" string disappears and the compile throws many errors and I do not understand why. since if it would not be easier to do directly p = v; and ready.

I leave the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*duplicar(char*);
main()
{
 char *p,*v;
 v=(char*)malloc(4*sizeof(char));
 v="sip";
 p=duplicar(v);
 free(v);                             //con el free no funciona ?poque¿
 printf("%s\n",p);
 return 0;
}
char*duplicar(char*v)
{
 int l,i;
 char *k;
 l=strlen(v); 
 if(l==0)
  {
   k=NULL;  
  }
 k=(char*)malloc(l*sizeof(char)); //si malloc falla retorna NULL
 for(i=0;i<l;i++)
  {
   *(k+i)=*(v+i);
  }
 return k;
}

I leave the error returned by the compiler

* Error in './ej14': double free or corruption (! prev): 0x08048600 * ======= Backtrace: ========= /lib/i386-linux-gnu/libc.so.6[0x4a5f871b] /lib/i386-linux-gnu/libc.so.6[0x4a5f9460] ./ej14[0x80484f9] /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x4a59c5b5] ./ej14[0x80483e1] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 00: 0e 10148 / home / knoppix / ej14 08049000-0804a000 rw-p 00000000 00: 0e 10148 / home / knoppix / ej14 0804a000-0806b000 rw-p 00000000 00:00 0 [heap] 4a560000-4a57f000 r-xp 00000000 00: 0e 25 /UNIONFS/lib/i386-linux-gnu/ld-2.17.so 4a57f000-4a580000 r - p 0001f000 00: 0e 25 /UNIONFS/lib/i386-linux-gnu/ld-2.17.so 4a580000-4a581000 rw-p 00020000 00: 0e 25 /UNIONFS/lib/i386-linux-gnu/ld-2.17.so 4a583000-4a6f1000 r-xp 00000000 00: 0e 30 /UNIONFS/lib/i386-linux-gnu/libc-2.17.so 4a6f1000-4a6f2000 --- p 0016e000 00: 0e 30 /UNIONFS/lib/i386-linux-gnu/libc-2.17.so 4a6f2000-4a6f4000 r - p 0016e000 00: 0e 30 /UNIONFS/lib/i386-linux-gnu/libc-2.17.so 4a6f4000-4a6f5000 rw-p 00170000 00: 0e 30 /UNIONFS/lib/i386-linux-gnu/libc-2.17.so 4a6f5000-4a6f8000 rw-p 00000000 00:00 0 4b848000-4b864000 r-xp 00000000 00: 0e 8031 /UNIONFS/lib/i386-linux-gnu/libgcc_s.so.1 4b864000-4b865000 rw-p 0001b000 00: 0e 8031 /UNIONFS/lib/i386-linux-gnu/libgcc_s.so.1 b774e000-b774f000 rw-p 00000000 00:00 0 b7760000-b7763000 rw-p 00000000 00:00 0 bfefd000-bff1e000 rw-p 00000000 00:00 0 [stack] ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso] Aborted

    
asked by juliancaba 04.09.2016 в 07:26
source

2 answers

2

The problem is that you are doing free on a pointer that has not been obtained with malloc , calloc or realloc .

The following program, much simpler, has the same problem:

#include <stdlib.h>
main()
{
 char *v;
 v=(char*)malloc(4*sizeof(char));
 v="sip";
 free(v);                             //con el free no funciona ?poque¿
 return 0;
}

malloc reserves a memory area of size of 4 chars and returns a pointer that points to that memory area and that pointer is assigned to v .

v="sip" does not copy the string "sip" to the memory area that is pointed to by v but instead assigns a different pointer to v ; this other pointer points to another memory area where the compiler has placed the "sip" string. Therefore the pointer that returned malloc is lost.

When you make free(v) in v there is no pointer obtained with malloc , calloc or realloc ; That's why it fails.

The following program does work:

#include <stdlib.h>
#include <string.h>
main()
{
 char *v;
 v=(char*)malloc(4*sizeof(char));
 strcpy(v, "sip" );
 free(v);          //Ahora sí funciona con el free
 return 0;
}

In this we use strcpy(v, "sip") instead of v="sip" . strcpy does not modify v , v continues to point to a memory area of 4 chars size that returned malloc . What strcpy does is copy the four characters of the string "sip" to the memory area that is pointed to by v .

    
answered by 05.09.2016 / 00:37
source
1

C is not my favorite language but I'm very interested in it.

I was testing the online rextester compiler, with the C (gcc) option, a very useful tool, by the way, and told me that the error is in line v="sip"; because free can only be applied to the heap or heap .

"sip" is taken as constant and the compiler stores it in the stack or Stack , which prevents the use of free .

Then I made a function str2p ( stringToPointer ) that assigns the characters of the literal constant in a variable:

//gcc 4.9.3

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


#define    STR_LEN    4    // El tamaño del string, más el caracter nulo '
//gcc 4.9.3

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


#define    STR_LEN    4    // El tamaño del string, más el caracter nulo '%pre%'


void str2p (char[], char*, int );    // Asigna los char de char[] en la variable apuntada por char*
char* duplicar ( char* );            // Retorna una copia de los char del argumento char*


int main()
{
    char *p,*v;


    // Reserva memoria para el string.
    v = (char*)malloc(STR_LEN * sizeof(char));

    // Asigna la constante string "sip" a la variable v.
    str2p("sip", v, STR_LEN);
    // Nótese que si la constante fuese más extensa,
    // por ejemplo "sip123", sólo las primeras STR_LEN-1 letras podrán asignarse.       

//    v="sip";    // <-- Error: la constante "sip" va al Stack, lo que impide el free()

    printf("Variable v antes de free(v) = '%s'\n", v);
    printf("Variable p antes de free(v) = '%s'\n", p);

    p = duplicar (v);

    free(v);    // Ahora funciona.

    printf("Variable v después de free(v) = '%s'\n", v);
    printf("Variable p después de free(v) = '%s'\n", p);

    return 0;
}

void str2p (char c[], char* v, int len)
{   
    int t = strlen(c) + 1;    // +1 incluye el caracter nulo '%pre%'

    // Para evitar desbordes se elige la longitud menor.
    int menor = ((t < len) ? t : len) - 1;

    // Comienza la asignación, letra por letra.
    for (int i=0; i < menor; i++)    v[i] = c[i];            

    // En C es obligatorio que todas las strings terminen en un caracter nulo '%pre%'
    v[menor] = 0;
}

char* duplicar (char* origen)
{
    char* k;
    int l = strlen(origen) + 1;    // Recordar siempre agregar el +1 para el caracter nulo '%pre%'

    if ( l == 0 )    k = NULL;
    else             k = (char*)malloc(l*sizeof(char)); //si malloc falla retorna NULL

    if (k == NULL) return NULL;

    for ( int i = 0; i < l-1; i++ )    k[i] = origen[i];

    return k;
}
' void str2p (char[], char*, int ); // Asigna los char de char[] en la variable apuntada por char* char* duplicar ( char* ); // Retorna una copia de los char del argumento char* int main() { char *p,*v; // Reserva memoria para el string. v = (char*)malloc(STR_LEN * sizeof(char)); // Asigna la constante string "sip" a la variable v. str2p("sip", v, STR_LEN); // Nótese que si la constante fuese más extensa, // por ejemplo "sip123", sólo las primeras STR_LEN-1 letras podrán asignarse. // v="sip"; // <-- Error: la constante "sip" va al Stack, lo que impide el free() printf("Variable v antes de free(v) = '%s'\n", v); printf("Variable p antes de free(v) = '%s'\n", p); p = duplicar (v); free(v); // Ahora funciona. printf("Variable v después de free(v) = '%s'\n", v); printf("Variable p después de free(v) = '%s'\n", p); return 0; } void str2p (char c[], char* v, int len) { int t = strlen(c) + 1; // +1 incluye el caracter nulo '%pre%' // Para evitar desbordes se elige la longitud menor. int menor = ((t < len) ? t : len) - 1; // Comienza la asignación, letra por letra. for (int i=0; i < menor; i++) v[i] = c[i]; // En C es obligatorio que todas las strings terminen en un caracter nulo '%pre%' v[menor] = 0; } char* duplicar (char* origen) { char* k; int l = strlen(origen) + 1; // Recordar siempre agregar el +1 para el caracter nulo '%pre%' if ( l == 0 ) k = NULL; else k = (char*)malloc(l*sizeof(char)); //si malloc falla retorna NULL if (k == NULL) return NULL; for ( int i = 0; i < l-1; i++ ) k[i] = origen[i]; return k; }

The exercise is stored in rextester.com

    
answered by 04.09.2016 в 23:20