2011-11-06 23 views
7

Hoy encontré un problema muy extraño. En resumen, mi función devuelve un valor, la persona que llama obtiene un valor diferente. En algún lugar alrededor de mi código que tengo una llamada a:Función C cambio de valor a la vuelta. Pila corrupta?

Message* m = NULL; 
m = connection_receive(c); 

Dónde connection_receive se define como sigue:

Message* connection_receive(Connection* c) 
{ 
Message* k; 

    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      k = NULL; 
     else 
      k = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
     /* Until here, k is reachable and contains the correct data. */ 
     return k; 
    } 
    else 
     return NULL; 
} 

Aquí está un funcionamiento GDB, me detuve justo antes del retorno y justo después de la misión:

222   return k; 
(gdb) p k 
$1 = (Message *) 0x7ffff0000950 
(gdb) n 
226 } 
(gdb) n 
main() at src/main.c:57 
57    if (m) 
(gdb) p m 
$2 = (Message *) 0xfffffffff0000950 

Por supuesto, si intentamos acceder a 0xfffffffff0000950, tendremos un error de segmentación.

Si cambio la función y en lugar de devolver un valor, utilizando un segundo parámetro para pasar el valor funciona, pero me gustaría saber qué salió mal en este caso.

Muchas gracias.

EDITAR: Esto funciona, pero no es conveniente. Y también me gustaría saber por qué ocurre un error tan extraño.

void connection_receive2(Connection* c, Message** m) 
{ 
    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      *m = NULL; 
     else 
      *m = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
    } 
    else 
     *m = NULL; 
} 

Edit2: resuelto. Gracias a todos. El problema era un error tipográfico en el archivo de encabezado. No puedo usar -Werror porque necesito hacer cosas que levantan algunas advertencias, y en una salida grande y un encabezado grande, lo perdí.

+0

Tuve que suceder una vez. 'fin' mostró un valor de retorno y la variable en la que se almacenó mostró otro. Una recompilación lo arregló para mí (ni siquiera cambió la fuente); Lo mejor que puedo adivinar es que un archivo objeto dependiente no se volvió a compilar, de lo contrario posiblemente un error (raramente encontrado) en gcc. – Kevin

+0

Debe reducir esto a [SSCCE] (http://sscce.org/) que demuestre el problema y lo publique; no hay nada de malo con el código que ha publicado; el problema está en otra parte. –

+0

@BrianRoach, veré qué puedo hacer. Es un gran proyecto. – Victor

Respuesta

5
  1. ¿Cómo se define su m?
  2. ¿Tiene su llamante acceso al prototipo correcto?
  3. ¿En qué arquitectura estás?

Sospecho que hay una discrepancia con los tipos y que mi pregunta 2 es el meollo de todo.

Está devolviendo un puntero con (supongo) 48 o 64 bits. La persona que llama, sin embargo, piensa obtener un int, que tiene tal vez 32 bits y está firmado. Al convertir de nuevo a un puntero, el valor obtiene el signo extendido.

+4

+1, estoy bastante seguro (2) es correcto. Esta es la razón por la que siempre debe desarrollarse con el máximo conjunto de advertencias de compilación ('-Wall -Werror' en gcc), ya que detectará este tipo de cosas. –

+0

sí, la mitad inferior del valor de retorno es exactamente la misma, es muy sospechoso. –

+0

@dherefromhere \t Lo siento, se me olvidó decir. Mi "m" también es un Mensaje *. Sí, la persona que llama tiene acceso al mismo prototipo, de hecho estoy probando el módulo. Ni -Wall ni -Wextra me dan nada, se está compilando como un amuleto. Estoy construyendo y ejecutándolo en un Fedora 15, 2.6.40.6-0 64bits – Victor

0

¿Ha pulsado un objeto malloc: ed en la cola? Si no, y en lugar de eso, empujaste un objeto de pila, entonces es posible que termines con un comportamiento extraño cuando abres elementos.

+0

Es un objeto malloc'ed. Edité la publicación original y publiqué una definición equivalente que funciona bien. ¡Es realmente extraño! – Victor

0

Tuvimos el mismo problema y la causa principal fue la declaración implícita de la función connection_receive(). Por lo tanto, fue predeterminado a int que se firmó y luego se almacenó en m.

Cuestiones relacionadas