<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 14 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EstiloCorreo17
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 3.0cm 70.85pt 3.0cm;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=ES link=blue vlink=purple><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Hola,<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Antes de nada muchas gracias por tu rápida y precisa respuesta.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>La verdad es que la forma que me sugerías es mucho mejor y he cambiado la estructura para adecuarla a tus indicaciones:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>char *inserta(char* mensaje, char* cadena, int posicion)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>{<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      char *salida = NULL;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      int lcadena, lmensaje;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      char paso;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      salida = (char*) malloc(512);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      lmensaje = longitud(mensaje);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>                                                   <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      //copia la parte de la cadena antes de la posición de inserción<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>                  memcpy(salida,mensaje,posicion);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>                  salida+=posicion;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>                  mensaje+=posicion;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      //inserta la cadena en este punto<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      lcadena = longitud(cadena);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      memcpy(salida,cadena,lcadena);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      salida+=lcadena;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      //acaba de completar la cadena de salida con el resto del mensaje<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      memcpy(salida,mensaje,(lmensaje-posicion));<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      salida+=(lmensaje-posicion);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      *salida = 0x00;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      salida -= (lcadena+lmensaje);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      memcpy(cadena,salida,(lcadena+lmensaje+1));<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>                  free(salida);<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>      return cadena;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>}<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>El caso es que me sigue pasando, he comprobado que cuando creo el puntero salida tiene la dirección de memoria 0x8d10c8 y justo antes de ejecutar free(salida) tiene exactamente la misma dirección.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>¿Cómo me sugieres que haga la copia del puntero que me indicabas?...<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Gracias de nuevo.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p> </o:p></span></p><p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>De:</span></b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> Cconclase [mailto:cconclase-bounces@listas.conclase.net] <b>En nombre de </b>Salvador Pozo<br><b>Enviado el:</b> miércoles, 29 de octubre de 2014 12:29<br><b>Para:</b> Lista de correo sobre C y C++<br><b>Asunto:</b> Re: [C con Clase] Segmentation fault al ejecutar la sentencia free() en una función<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><div><div><div><div><div><div><div><div><div><div><p class=MsoNormal style='margin-bottom:12.0pt'>Hola:<o:p></o:p></p></div><p class=MsoNormal>El programa aparentemente está bien. No he podido probarlo porque no dispongo de la implementación de la función "longitud", pero he usado la función estándar "strlen", y no se producen errores.<o:p></o:p></p></div><p class=MsoNormal style='margin-bottom:12.0pt'>Esto me lleva a pensar que, con toda probabilidad, el error está en la función "longitud", que debe calcular mal la longitud de la cadena. Este error hace que el valor calculado de "salida" justo antes del "free" no esa exactamente el original, y el "segmentation fault" se produce al intentar liberar memoria en una dirección incorrecta.<o:p></o:p></p></div><p class=MsoNormal style='margin-bottom:12.0pt'>Además de esto, me gustaría comentar algunas cosas.<o:p></o:p></p></div><p class=MsoNormal>1) Con respecto a la función memcpy, decir que esta función está optimizada para copiar bloques de memoria. Hasta tal punto puede ser así que, probablemente, sólo se usa una instrucción de código máquina para ese copiado, de modo que usarla en un bucle para copiar datos de direcciones consecutivas es bastante ineficaz.<o:p></o:p></p></div><p class=MsoNormal>En lugar de esto:<o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>      for (int i = 0; i < posicion; i++)<o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>      {<o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>          memcpy(salida,mensaje,1);<o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>          salida++;<o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>          mensaje++;<o:p></o:p></p><p class=MsoNormal>      }<o:p></o:p></p></div><p class=MsoNormal style='margin-bottom:12.0pt'>Es mucho mejor usar esto:<o:p></o:p></p></div><p class=MsoNormal>memcpy(salida,mensaje,posicion);<o:p></o:p></p></div><p class=MsoNormal>salida+=posicion;<o:p></o:p></p></div><p class=MsoNormal>mensaje+=posicion;<o:p></o:p></p><div><div><div><div><div><div><div><div><div><div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal style='margin-bottom:12.0pt'>2) De hecho, para copiar cadenas es mejor usar strcpy, o en tu caso, strncpy. Esta segunda permite indicar el número máximo de caracteres a copiar.<o:p></o:p></p></div><div><p class=MsoNormal style='margin-bottom:12.0pt'>3) Para evitar cuentas al final, a la hora de liberar memoria, tal vez sería más interesante guardar una copia del puntero "salida". Esto nos asegura que no perdemos su valor, aunque alguna de las cuentas esté mal o haya algún error no previsto.<o:p></o:p></p></div><div><p class=MsoNormal>Hasta pronto.<br clear=all>-- <o:p></o:p></p><div><p class=MsoNormal>Salvador Pozo Coronado<br><a href="http://www.conclase.net" target="_blank">http://www.conclase.net</a><br>Blog con Clase: <a href="http://blogconclase.wordpress.com" target="_blank">http://blogconclase.wordpress.com</a><br>mailto:<a href="mailto:salvapozo@gmail.com" target="_blank">salvapozo@gmail.com</a><o:p></o:p></p></div></div></div></div></div></div></div></div></div></div></div></div></div><p class=MsoNormal><br><br><o:p></o:p></p></div></body></html>