[C con Clase] otro error mysql-c

Steven Davidson steven en conclase.net
Vie Jul 6 04:57:49 CEST 2007


Hola Duna,

El pasado 2007-06-28 11:28:37, Duna escribió:

D> Hola.
D> >Si te funciona bien con un array y no con un puntero, entonces esto
D> confirmaría las sospechas que no creaste memoria dinámicamente para
D> 'titulo', cuando era un >puntero.
D> Eso me ha alegrado mucho, pero ahora lo que me da miedo es lo del int, que
D> eso ya no es un puntero.

Sí, eso es preocupante. Veremos esto cuando lleguemos a ello en el código.

D> Probado, y sigue dándome NULL consulta3...

Esto sí que me preocupa. Viendo el código fuente, la única sentencia anterior con 'consulta3' es a la hora de crear memoria dinámicamente.

D> >Recuerda que sólo tienes que liberar los punteros que tú mismo creaste con
D> 'malloc()' u otra función alternativa.
D> Hecho también, soy una buena alumna.

Muy bien :-)

D> Y te mando el código final, si te parece, pero de la parte en la que me da
D> error.

Pedí todo el código para que pudiéramos recrear el problema nosotros mismos y hacer cualesquier comprobaciones que hagan falta para determinar el o los errores. Si nos das parte del código, no podremos recrear el "experimento" y nos quedamos como estábamos antes: nosotros dándote pistas, y tú comprobando. En general, esto funciona, pero en tu caso, creo que nuestras respuestas van a ser las mismas que antes :-(

D> A ver, la estructura:
D> struct dos_l
D> {
D>         int cl;
D>         char* titulo;

Dijiste que cambiaste esto por un array.

D>         int ce;
D>         struct dos_l * next;
D> };
D> Y la función:
D> dos_l* consulta_bdos_1 (char * recibida)

Cambia el tipo del parámetro a 'const char *'. Ya de paso, comprueba que 'recibida' no sea un puntero nulo.

D> {
D>         int i, j, l, k;
D>         MYSQL_RES *res3;
D>         MYSQL_ROW row;
D>         unsigned long *lon;
D>         MYSQL * base;
D>         dos_l *consulta3, *primero, *anterior;

Inicializa estos punteros. Por ejemplo,

dos_l *consulta3=NULL, *primero=NULL, *anterior=NULL;

Viendo que usas C++, sería mejor usar 0 (cero) en lugar de 'NULL'.

D>         printf ("\nllego a consultar bases\n");
D>         base = new MYSQL;
D>         mysql_init(base);
D>                 if(!(base = mysql_init(0)))

Esto no tiene sentido. O dejas a 'mysql_init()' crear la memoria para 'base' o lo haces tú misma; pero no ambas formas simultáneamente. Si te das cuenta, llamas a 'mysql_init()' dos veces, lo cual puede provocar algú que otro error en la sesión de MYSQL.

[CORTE]

D>                 // Hacer una consulta con el comando "SELECT * FROM gente":
D>                  if(mysql_query(base, recibida))

Deberías usar 'mysql_real_query()', ya que es una implementación más rápida y mejorada de esta función.

D>                  {
D>                         // Error al realizar la consulta:
D>                         printf( "ERROR: %s\n",mysql_error(base));
D>                         mysql_close(base);
D>                         rewind(stdin);
D>                         getchar();
D>                 }
D>                  if((res3 = mysql_store_result(base)))
D>                  {
D>                         i = (int) mysql_num_rows(res3);
D>                         j = (int) mysql_num_fields(res3);
D>                         printf ("\nEl número de resultados es: %d\n", i);
D>                         if (i!=0)
D>                         {
D>                                 l=1;
D>                                 primero=NULL;
D>                                 anterior=NULL;
D>                                 for(l = 0; l < i; l++)
D>                                 {
D>                                         consulta3 = (dos_l *)malloc (sizeof
D> (dos_l));
D>                                         row = mysql_fetch_row(res3);
D>                                         lon = mysql_fetch_lengths(res3);
D>                                         printf ( "Registro no. %d", l+1);
D>                                         // Mostrar cada campo y su
D> longitud:
D>                                         k=0;
D>                                         if( consulta3==NULL )

Aquí dices que te da el error. Si esto esto es así, entonces tienes un problema MUY grave. Esto es porque la única posibilidad de que 'consulta3' sea un puntero nulo es si 'malloc()' no haya podido adjudicar memoria dinámicamente. Para esta situación, no hay mucho que se pueda hacer al respecto. Personalmente, me parece extremadamente raro que esto ocurra, por lo que me hace sospechar que el error ocurre en alguna iteración tardía. Esto significaría que existen muchísimos tuplos (filas) en tu base de datos.

Intenta averiguar si existe un error mientras llamas a 'malloc()'. Revisa el valor de 'errno' o si prefieres, invoca 'strerror()' para mostrar un mensaje descriptivo basado en el error particular. O sea,

if( NULL == consulta3 )
  perror( strerror( errno ) );

Ya de paso, averigua en qué iteración estábamos cuando se provocó este error. Por ejemplo,

if( NULL == consulta3 )
{
  fprintf( stderr,  "Iteración #%d: ", l );
  perror( strerror( errno ) );
}

D>                                          fputs( "ERROR: consulta3 es nulo",
D> stderr );
D>                                        else if( row ==NULL )
D>                                          fputs( "ERROR: row es nulo",
D> stderr );
D>                                        else if(row[k] ==NULL )
D>                                          fputs( "ERROR: row[k] es nulo",
D> stderr );
D>                                        else
D>                                         consulta3->cl = atoi (row[k]);

Aquí deberías agrupar todas estas sentencias bajo el mismo ámbito para formar parte de 'else'. Algo como,

else
{
  consulta3->cl = atoi( row[k] );
  ...
}

D>                                         printf ("\n%d", consulta3->cl);
D>                                         printf (" ");
D>                                         k++;
D>                                         consulta3->titulo = row[k];

Recuerda que esto no se puede hacer con arrays. Tendrías que usar 'strcpy()' o 'strncpy()' haciendo uso del array 'lon' para indicar la cantidad de caracteres. Por ejemplo,

strncpy( consulta3->titulo, row[k], lon[k]+1 );

D>                                         printf ("\n%s", consulta3->titulo);
D>                                         printf (" ");
D>                                         k++;
D>                                         consulta3->ce = atoi (row[k]);
D>                                         printf ("\n%d", consulta3->ce);
D>                                         printf (" ");
D>                                         consulta3->next=NULL;
D>                                         if (primero == NULL)
D>                                                 primero=consulta3;
D>                                         else
D>                                                 anterior->next=consulta3;
D>                                         anterior=consulta3;
D>                                 }
D>                         }
D>                  }
D>                  if (i != 0)
D>                  {
D>                         consulta3->next=NULL;
D>                         consulta3=primero;
D>                  }
D>                  if (i==0)
D>                  {
D>                          consulta3=NULL;
D>                  }

Creo que mencioné algunos comentarios acerca de estas sentencias en algún otro correo-e anterior. Brevemente, no veo necesidad de "validar" 'consulta3'. Lo que realmente necesitas es el puntero 'primero' y nada más. La razón de usar 'primero' es para apuntar a la cabeza de la lista y al primer nodo de ésta.

D>                  //mysql_free_result(res3);
D>                  mysql_close(base);
D>                  return (consulta3);

Retorna 'primero' que es lo que nos interesa.

D> }
D> >Espero que podamos solucionar el problema, antes de que "te dé algo".
D> Parece que me conoces hace años...jejeje

Veo que usas C++, aunque estés usando funciones de C. Si no puedes sacar nada en claro y los errores siguen apareciendo por culpa de 'consulta3', entonces usa el operador 'new' en lugar de la función 'malloc()'. No creo que resuelva el problema, pero ya eso por probar algo diferente :(


Sin poder hacer pruebas por nuestra cuenta, no podemos establecer el problema exacto. Espero que esto ayude un poco.

Steven


Más información sobre la lista de distribución Cconclase