Dirección de retorno de Strdup fuera de límites

Pensé en preguntar antes de pasar más horas en esto. Valgrind no informa nada, de hecho, no se bloquea con Valgrind.

char* a = "HI"; char* b = strdup(a); 

(gdb) imprimir b => $8 = 0xffffffffe8003680

Esto solo sucede en mi biblioteca compartida cargada dinámicamente, (cargada con dlopen). No tengo idea de lo que podría causar esto. Quité casi todo de esa biblioteca, solo hay estas dos líneas en ella. ¿Puedes ayudarme a depurar esto?

Si bash acceder a b ahora:

 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6 

¿Qué podría estar yendo mal aquí?

Backtrace:

 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6 (gdb) bt #0 0x00007ffff76b3d0a in strchrnul () from /lib64/libc.so.6 #1 0x00007ffff767088a in vfprintf () from /lib64/libc.so.6 #2 0x00007ffff767af79 in printf () from /lib64/libc.so.6 #3 0x00007ffff722678c in _mkp_stage_30 (plugin=0x61f420, cs=0x7fffe8002040, sr=0x7fffe8003070) at hello.c:68 #4 0x000000000040f93a in mk_plugin_stage_run (hook=16, socket=18, conx=0x0, cs=0x7fffe8002040, sr=0x7fffe8003070) at mk_plugin.c:558 #5 0x000000000040c501 in mk_http_init (cs=0x7fffe8002040, sr=0x7fffe8003070) at mk_http.c:255 #6 0x0000000000404870 in mk_request_process (cs=0x7fffe8002040, sr=0x7fffe8003070) at mk_request.c:510 #7 0x0000000000404d75 in mk_handler_write (socket=18, cs=0x7fffe8002040) at mk_request.c:630 #8 0x000000000040b446 in mk_conn_write (socket=18) at mk_connection.c:130 #9 0x0000000000409352 in mk_epoll_init (efd=12, handler=0x7fffe8001690, max_events=202) at mk_epoll.c:102 #10 0x0000000000409b4e in mk_sched_launch_worker_loop (thread_conf=0x61a5a0) at mk_scheduler.c:196 #11 0x00007ffff79c2f05 in start_thread () from /lib64/libpthread.so.0 #12 0x00007ffff770553d in clone () from /lib64/libc.so.6 

Necesitas agregar

 #include  

Para obtener la statement de strdup() .

O, si ya tienes eso, debes invocar tu comstackdor de una manera que haga que strdup() visible (ver más abajo para más detalles). strdup() está definido por POSIX, no por ISO C.

gcc habilita la (s) macro (s) apropiada (s) por defecto, pero el uso de -ansi o -std=c99 deshabilitará También puede agregar un #define apropiado a la parte superior de su archivo fuente.

En ausencia de una statement visible, el comstackdor asume (bajo las reglas C90) que strdup() devuelve int . Esto resulta en un comportamiento indefinido. En particular, si int es de 32 bits y char* es de 64 bits, sucederán cosas malas. (Bajo las reglas de C99, llamar a una función sin una statement visible es una violación de restricción).

También debe boost los niveles de advertencia de su comstackdor y prestar atención a las advertencias . Un problema como este debería manifestarse en tiempo de comstackción; No deberías tener que diagnosticar el comportamiento en tiempo de ejecución.

ACTUALIZACIÓN:

Lo siguiente se basa en documentación y experimentos en mi propio sistema Ubuntu 11.04. Es probable que se aplique a cualquier sistema que use glibc; parte de esto podría aplicarse a sistemas que no sean glibc. man strdup y man feature_test_macros para más información.

Para usar strdup() , debe tener #include para que la statement sea visible. (El comstackdor no necesariamente se quejará si omites esto, pero de todos modos lo necesitas).

Además, debe tener uno de los siguientes (o equivalente) antes de #include :

 #define _SVID_SOURCE 

 #define _BSD_SOURCE 

 #define _XOPEN_SOURCE 500 /* or greater */ 

 #define _XOPEN_SOURCE #define _XOPEN_SOURCE_EXTENDED 

 #define _POSIX_C_SOURCE 200809L /* or greater */ 

La forma más sencilla de hacer esto es simplemente no usar la -ansi o -std=... para gcc (o el equivalente para clang); gcc habilita algunas de estas macros por defecto.

Si desea comstackr con -ansi o std=c99 , entonces puede establecer explícitamente una de las macros anteriores (o dos si usa la 4ª alternativa), ya sea con un #define explícito en la fuente (probablemente la mejor solución), o utilizando, por ejemplo, gcc -std=c99 -D_XOPEN_SOURCE=500 .

Y , como mencioné antes, debe boost los niveles de advertencia en su comstackdor. Para gcc, normalmente uso:

 gcc -std=c99 -pedantic -Wall -Wextra -O3 

El -O3 permite optimizaciones; Un efecto colateral es que permite el análisis necesario para realizar esas optimizaciones, que pueden detectar una serie de problemas que no son evidentes en niveles de optimización más bajos.

El motivo de todo este rigmarole es que strdup() no está definido por el estándar ANSI / ISO C (el comité decidió no incluirlo), pero POSIX lo define y su statement está en , Una de las cabeceras estándar de la norma ISO C. En el estricto modo de conformidad con ISO C, el nombre strdup() no puede hacerse visible en . Tienes que tomar estos pasos adicionales para decirle al comstackdor que lo haga visible de todos modos. (gcc no es un comstackdor de C totalmente conforme de forma predeterminada, por lo que es capaz de hacer que strdup() visible de forma predeterminada).

Dado que strdup() es una función tan simple, puede considerar simplemente escribir su propia implementación en el estándar ISO C y usarla en su lugar. Por ejemplo (tenga en cuenta que los nombres que comienzan con str están reservados):

 char *dupstr(const char *s) { char *const result = malloc(strlen(s) + 1); if (result != NULL) { strcpy(result, s); } return result; } 

(Solo he probado esto de manera mínima). Si strdup() es la única función específica de POSIX que está usando, la mejor solución sería utilizar la propia solución. Si estás usando otras funciones específicas de POSIX, entonces tendrás que lidiar con todas estas cosas de todos modos, y también podrías usar strdup() .

Parece que estás llamando incorrectamente a printf (). En lugar de printf (b), necesita hacer:

 printf("%s\n", b); 

Edición: Añadido \ n arriba, gracias a Jonathan.