Ver Mensaje Individual
  #2 (permalink)  
Antiguo 07/05/2014, 12:37
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 12 años, 3 meses
Puntos: 83
Respuesta: dudas de memoria dinamica

Ejecuta tu codigo en el depurador, y veras que hay cosas que no funcionan.

Ya se que no debo hacerlo, pero te cuelgo un codigo completo de tal como resolveria la lista (no es la unica forma ni la mas eficiente, pero puedes sacar ideas); debajo te comento un par de cosas (de todas formas he comentado las lineas mas interesantes del codigo):

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3. void fflush_stdin() {
  4.     char c;
  5.     while((c = getchar()) != EOF && c != '\n');
  6. }
  7.  
  8.  
  9. int main() {
  10.     int *lista, *temporal, contador, input, q;
  11.     size_t szmem;
  12.  
  13.     lista = 0;
  14.     contador = 0;
  15.  
  16.     //bucle infinito
  17.     while(1) {
  18.         //añadir elemento
  19.         printf("Quieres añadir un elemento? (s/n)");
  20.         if(getchar() != 's') {
  21.             break;
  22.         }
  23.        
  24.         //recupera input de usuario
  25.         printf("Dime el valor para la posicion %d:" , contador);
  26.         scanf("%d", &input);
  27.         fflush_stdin();
  28.        
  29.         //determina nueva posicion y tamaño de la lista
  30.         contador++;
  31.         szmem = sizeof(int) * contador;
  32.  
  33.         //reserva memoria
  34.         if(!lista) {
  35.             //nueva lista
  36.             if(!(lista = malloc(szmem))) {
  37.                 //memoria insuficiente
  38.                 break;
  39.             }
  40.         }
  41.         else {
  42.             //expande lista existente
  43.             if(!(temporal = realloc(lista, szmem))) {
  44.                 //memoria insuficiente
  45.                 break;
  46.             }
  47.             //restablece lista
  48.             lista = temporal;
  49.         }
  50.        
  51.         //asigna valor
  52.         *(lista + contador - 1) = input;
  53.        
  54.         //valor insertado
  55.         //printf("%d=>%d\n", contador, *(lista + contador - 1));
  56.     }
  57.  
  58.     //final
  59.     if(lista) {
  60.         //volcar lista
  61.         for(q = 0; q < contador; q++) {
  62.             printf("%d=>%d\n", q, *(lista + q));
  63.         }
  64.        
  65.         //libera memoria
  66.         free(lista);
  67.     }
  68.  
  69.     return 0;
  70. }

Observa la linea del realloc: esta funcion en caso de exito retorna la nueva posicion del bloque de memoria, y retorna nulo en caso de error. Eso significa que en caso de exito la linea que tienes en tu codigo provocará una violacion de segmento en el siguiente acceso a la lista:

Código C:
Ver original
  1. //esto es parte de tu codigo, linea 24
  2. realloc(lista,i+1*sizeof(int));

En caso de exito el bloque previo de lista será movido a otra posicion para albergar la nueva memoria solicitada, es decir que la posicion previa de lista ya no está disponible, y los siguientes intentos de acceso a 'lista' provocan el segfault. Se soluciona tal como te dejo en el ejemplo: asignar el retorno a una variable temporal sobre la que vas a hacer las comprovaciones. Si asignas el retorno de realoc a la misma variable, en caso de error no podras recuperar el bloque previo y provocaras una perdida de memoria, por eso se usa una variable temporal intermediaria.

De forma parecida tienes que escanear el nuevo valor en una variable auxiliar, en vez de directamente en la posicion de memoria. De esta forma puedes hacer comprovaciones y decidir si ese valor es valido para la lista.

Revisa este ejemplo y compara con el codigo que colgaste, si hay algo (una duda o un error por mi parte) ya sabes que puedes comentarlo aqui mismo ;)

Espero que te sea de ayuda.

Saludos
vosk


p.s. una ultima observacion:

Código C:
Ver original
  1. //parte de tu codigo, linea 18
  2. printf("\nElemento %d de la lista enlazada y preciona...

'preciona' va con 's' :), saludos