• Jueves 14 de Noviembre de 2024, 04:29

Autor Tema:  Violacion de segmento al modificar el contenido de un puntero  (Leído 3085 veces)

sergio_

  • Nuevo Miembro
  • *
  • Mensajes: 7
    • Ver Perfil
Violacion de segmento al modificar el contenido de un puntero
« en: Sábado 24 de Septiembre de 2011, 02:56 »
0
Buenas gente, les paso a comentar lo que me ocurre y queria saber si alguien me puede decir porque me pasa esto.

Código: C
  1.         char buffer[8] = "hola com";
  2.         char* buffer2 = "hola com";
  3.  
  4.         buffer[0]='a';
  5.         buffer2[0] = 'a';
  6.  

Para el caso en que escribo buffer, anda lo mas bien, pero para el caso en que quiero escribir buffer2, me da violacion de segmento. No se si sera algo propio del ambiente unix o que, pero no se porque me ocurre esto. estoy modificando el contenido del puntero nada mas.

Tmb me ocurre en este caso:

Código: C
  1.  
  2. int* a = 123;
  3. *a = 245;
  4.  
  5.  

Bueno, si alguien me puede decir cual es el error se agradece.

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re:Violacion de segmento al modificar el contenido de un puntero
« Respuesta #1 en: Sábado 24 de Septiembre de 2011, 16:04 »
0
Hola sergio_, bienvenido al foro :)

Estas cometiendo el clasico error al trabajar con punteros, usar punteros sin inicializar.

Por si no lo sabias, un puntero es un tipo especial de variable que guarda direcciones de memoria, nada mas. Para poder utilizarlo sin problemas debemos decirle que guarde (apunte) una direccion de memoria libre. Esto se hace por medio de la funcion malloc (si trabajas con C) que se encuentra en la libreria stdlib.h o el operador new (si trabajas con C++). Cuando termines de utilizar el apuntador, debes liberar la memoria. Si usaste malloc debes usar free para liberar, y si usaste new debes usar delete. Si no le decimos que apunte a una direccion especifica, apuntara a una direccion al azar de la memoria, es por eso que obtienes un segfault, ya que tu puntero apunta a una direccion de memoria no valida y tratas de cambiar su contenido.

Hay otro error ademas de ese en tu codigo, estas definiendo tu variable buffer como un arreglo de char de 8, cuando en realidad tu cadena contiene 9 caracteres, ya que todas las cadenas contienen obligatoriamente el caracter nulo '\0' (aunque tu no lo veas) al finalizar la cadena, para indicar que es el fin de la cadena. Aunque al inicializar arreglos de char no es necesario colocar el tamaño del arreglo, ya que el compilador lo deduce automaticamente, bien pudiste haber escrito  char buffer[] = "hola com"; y el compilador automaticamente deduce que el tamaño del arreglo es de 9 caracteres. Si quieres especificar el tamaño de tu arreglo y despues asignarle el valor la forma de hacerlo es por medio de la funcion strncpy() que esta definida en la libreria string.h:

Código: [Seleccionar]
char buffer[9];
strncpy(buffer, "hola com", 9);

Te dejo un ejemplo de como debes inicializar correctamente los punteros:

Código: [Seleccionar]
#include <cstdio>
#include <cstdlib>
#include <cstring>

int main()
{
    char buffer[] = "hola com";

    // Utiliza malloc si trabajas con C
    //char* buffer2 = (char*) malloc(sizeof(char) * 9);
    char* buffer2 = new char[9];
    strncpy(buffer2, "hola com", 9);

    buffer[0]='a';
    buffer2[0] = 'a';

    //int* a = (int*) malloc(sizeof(int));
    int* a = new int();
    *a = 123;
    *a = 245;

    // Si utilizaste malloc, usa free para liberar
    //free(buffer2);
    //free(a);
    delete buffer2;
    delete a;


    return 0;
}

Saludos :)

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================

sergio_

  • Nuevo Miembro
  • *
  • Mensajes: 7
    • Ver Perfil
Re:Violacion de segmento al modificar el contenido de un puntero
« Respuesta #2 en: Lunes 17 de Octubre de 2011, 01:00 »
0
Buenas!, volvi a la red, gracias por la ayuda!

Me olvide del "/0" xD
y sii, leyendo despues me di cuenta de lo que estaba haciendo mal, pasa que hace mucho no toco C T_T jajaj

Ya que estoy comento otra duda que tengo con respecto a la mem dinamica.

Yo tengo esto

Código: C
  1. typedef struct regOf{
  2.  
  3.         unsigned int offset;
  4.         unsigned int frec;
  5.  
  6. }regOF;
  7.  
  8. typedef struct TablaOffFrec{
  9.  
  10.         //En caso que la cantidad inicial de registros no sea suficiente y tenga que reallocar registros en la tabla
  11.         //Necesito saber cuando las recorra cuantos registros tiene la tabla en definitiva para serializar
  12.         unsigned int cantRegFinal;
  13.         char* nombArch;
  14.         //La tabla es un conjunto de registros
  15.         regOF* registros;
  16. }tablaOF;
  17.  
  18.  
  19.  
  20. int main(){
  21.         tablaOF* tabla = (tablaOF*)malloc(sizeof(tablaOF*));
  22.         tabla->registros = (regOF*)malloc(sizeof(regOF*));
  23.  
  24.         tabla->registros->offset=0;
  25.         tabla->registros->frec=10;
  26.  
  27.         printf("offset = %u\n",tabla->registros->offset);
  28.         printf("frec = %u\n",tabla->registros->frec);
  29.  
  30.         free(tabla->registros);
  31.         free(tabla);
  32. }
  33.  
  34.  
  35.  

Al mostrar por pantalla los valores se muestran bien. Pero al usar el valgrind para comprobar si pierdo memoria obtengo lo siguiente

Código: C
  1. ==9496== Memcheck, a memory error detector
  2. ==9496== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
  3. ==9496== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
  4. ==9496== Command: ./prueba
  5. ==9496==
  6. ==9496== Invalid write of size 4
  7. ==9496==    at 0x804845F: main (prueba.c:64)
  8. ==9496==  Address 0x419e030 is 4 bytes after a block of size 4 alloc'd
  9. ==9496==    at 0x4026864: malloc (vg_replace_malloc.c:236)
  10. ==9496==    by 0x8048448: main (prueba.c:63)
  11. ==9496==
  12. ==9496== Invalid read of size 4
  13. ==9496==    at 0x8048466: main (prueba.c:66)
  14. ==9496==  Address 0x419e030 is 4 bytes after a block of size 4 alloc'd
  15. ==9496==    at 0x4026864: malloc (vg_replace_malloc.c:236)
  16. ==9496==    by 0x8048448: main (prueba.c:63)
  17. ==9496==
  18. ==9496==
  19. ==9496== HEAP SUMMARY:
  20. ==9496==     in use at exit: 0 bytes in 0 blocks
  21. ==9496==   total heap usage: 2 allocs, 2 frees, 8 bytes allocated
  22. ==9496==
  23. ==9496== All heap blocks were freed -- no leaks are possible
  24. ==9496==
  25. ==9496== For counts of detected and suppressed errors, rerun with: -v
  26. ==9496== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 11 from 6)
  27.  

El error "write" se da al hacer el malloc de tabla->registros, y el "read" al hacer el free de lo mismo.

La idea mia es, poner en la tabla varios registros e ir llenandolos, pero detecte esto asiq no avanzo xD


Bueno, desde ya muchas gracias!!


sergio_

  • Nuevo Miembro
  • *
  • Mensajes: 7
    • Ver Perfil
Re:Violacion de segmento al modificar el contenido de un puntero
« Respuesta #3 en: Lunes 17 de Octubre de 2011, 11:54 »
0
Me acabo de dar cuenta de lo que pasaba :P


yo queria hacer

La tabla con un reg

entonces la forma correcta de hacerlo hubiera sido:

Código: C
  1.         tablaOF* tabla = (tablaOF*)malloc(sizeof(tablaOF));
  2.         tabla->registros = (regOF*)malloc(sizeof(regOF));
  3.  

Al hacer esto, estoy declarando un puntero del tipo tablaOF, que apunta a un lugar en memoria donde  tiene espacio para el contenido de la tabla
lo mismo con tabla->registros, es un puntero que apunta a un lugar de la memoria que puede tener los datos que lleva.

Igual corríjanme si estoy mal xD