c - una - ¿Por qué no puedo imprimir variables de entorno en gdb?
variable path linux (5)
Como grundprinzip dijo, use getenv (sz) y recuerde anular la verificación del valor de retorno
Alternativamente,
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[], char*[] environ) {
int i = 0;
while(environ[i]) {
printf("%s/n", environ[i++]);
}
return 0;
}
#include <unistd.h>
#include <stdio.h>
extern char **environ;
int main(int argc, char *argv[]) {
int i = 0;
while(environ[i]) {
printf("%s/n", environ[i++]);
}
return 0;
}
Aquí está mi ops:
(gdb) n
8 printf("%s/n", environ[i++]);
(gdb) p environ[i]
Cannot access memory at address 0x0
(gdb) n
LOGNAME=root
7 while(environ[i]) {
Como puede ver, printf
puede imprimir environ[i]
, pero p environ[i]
me da Cannot access memory at address 0x0
, ¿por qué?
No hay nada malo con tu código. Lo probé en mi máquina e imprimió el entorno como se esperaba. No debería necesitar usar getenv ().
¿Está ejecutando esta aplicación desde la terminal? Si no, deberías serlo. Otros medios para ejecutar una aplicación podrían ser invocar su binario sin pasarle el entorno.
Desde el terminal, ¿cuál es su salida cuando ejecuta "env"? Debería generar la misma lista que su programa. Lo hace en mi máquina.
Probablemente, el proceso de depuración se inicia con
execve(binary, NULL, NULL);
y el entorno extern char **environ
obtiene ese 2nd NULL
a pesar de que hay un entorno disponible.
Con un pequeño cambio, su programa funciona tanto de forma independiente como bajo gdb
.
/* #include <unistd.h> */ /* no more environ */
#include <stdio.h>
/* extern char **environ; */ /* no more environ */
int main(int argc, char *argv[]) {
int i = 0;
char **ptr = argv + argc + 1; /* points to environment, in Un*x */
while(ptr[i]) {
printf("%s/n", ptr[i++]);
}
return 0;
}
Por qué y cómo, ese NULL
se convierte al valor correcto dentro de gdb
no tengo ni idea.
Se accede a las variables de entorno en C / C ++ utilizando la función getenv()
definida en stdlib.h
. Sin embargo, usando el parámetro envp
de la función principal, puede usar el siguiente ejemplo para iterar sobre variables de entorno.
#include <stdio.h>
int main(int argc, char *argv[], char *envp[])
{
char **next = envp;
while (*next)
{
printf("%s/n", *next);
next++;
}
return 0;
}
Probado en una Mac
gdb resuelve el símbolo de environ
incorrecto. No obstante, no sé por qué. Vea a continuación por qué.
Pero puedes probarlo. Cambiar el programa a:
#include <unistd.h>
#include <stdio.h>
extern char **environ;
int main(int argc, char *argv[]) {
int i = 0;
printf("%p/n", &environ);
while(environ[i]) {
printf("%s/n", environ[i++]);
}
return 0;
}
Ahora ejecutemos esto en el depurador.
(gdb) n 7 printf("%p/n", &environ); (gdb) n 0x8049760 8 while(environ[i]) { (gdb) p &environ $1 = (char ***) 0x46328da0 (gdb)
Asi que. El programa real tiene, durante su vinculación, resuelto environ
a la dirección 0x8049760. Cuando gdb quiere acceder al símbolo de entorno, se resuelve en 0x46328da0, que es diferente.
Editar. Parece que su símbolo de environ
está realmente vinculado al símbolo environ@@GLIBC_2.0
. En gdb escribe esto:
(gdb) p environ
Y presiona la tecla tab (dos veces), autocompletará los símbolos. Cuyos rendimientos:
(gdb) p environ environ environ@@GLIBC_2.0
environ@@GLIBC_2.0
es el que en realidad está vinculado al environ@@GLIBC_2.0
extern char **environ
Imprimir esto produce la misma dirección que el programa ve, 0x8049760:
(gdb) p &''environ@@GLIBC_2.0'' $9 = ( *) 0x8049760 (gdb) p ((char**)''environ@@GLIBC_2.0'')[i] $10 = 0xbffff6ad "XDG_SESSION_ID=1"
Entonces, en un momento, glibc dejó de environ
símbolo del environ
y agregó una versión más nueva