Pregunta

Como muchos programadores jóvenes hacen, he aprendido la utilidad de la inserción de numerosas declaraciones de impresión a la consola de "here1", "aquí2", y así sucesivamente en diferentes puntos de código para averiguar cuando mis programas van mal. Esta técnica la fuerza bruta depuración me ha salvado muchas, muchas veces a lo largo de mis estudios CS. Sin embargo, cuando empecé a programar en C, me topé con un problema interesante. Si tuviera que tratar de ejecución

void* test;

printf("hello world");
test[5] = 234;

Por supuesto que conseguir un error de segmentación por no malloc'ing memoria para testChar. Sin embargo, se podría pensar lógicamente que "hola mundo" se imprime antes de que ocurra la falla seg, ya que es el flujo del código, pero en mi experiencia, siempre es el caso que la falla seg ocurra primero, y "hola mundo "Nunca se imprime en la consola en absoluto. (Yo no era capaz de probar este ejemplo exacta, pero me he encontrado con este tipo de situación, muchas veces usando gcc en una máquina Linux.) Supongo que esto tiene que ver ni con el compilador reordenación de algunas cosas y / o printf el uso de algún tipo de tampón que se elimina de forma asíncrona y por lo tanto no es inmediata. Esto es totalmente especulación de mi parte, porque, sinceramente, no sé por qué sucede. En cualquier otro lenguaje que he utilizado, no importa cuál es el problema causado la línea "testChar = ...", el "hola mundo" seguiría siendo impreso, y así pude determinar dónde está el problema.

Mi pregunta es ¿por qué sucede esto cuando estoy programando C? ¿Por qué no está el mundo hola imprimió por primera vez? Y en segundo lugar, hay una mejor técnica de depuración de programación C que esto que logra la misma cosa básica? Al igual que en, una forma fácil / intuitiva para encontrar la línea de código que es un problema?

Editar: Le di un ejemplo de trabajo por accidente jaja. Lo que tengo ahora debe causar una violación de segmento. Es curioso como por lo general cuando I no quiero una violación de segmento consigo uno, y ahora, cuando en realidad quería uno que escribí código legal!

¿Fue útil?

Solución

El código que envió es perfectamente legal y no debe causar una violación de segmento - no hay necesidad de nada malloc. El problema debe estar en otro lugar -. Por favor, puesto el ejemplo más pequeño de código que provoca el problema

Editar Ahora ha editado el código para tener un significado totalmente diferente. Sin embargo, la razón por la que "hola mundo" no aparece es que el búfer de salida no ha sido lavado. Trate addinig

fflush( stdout );

después de la printf.

En cuanto a la localización de la fuente del problema que tiene un par de opciones:

  • espolvorear generosamente printfs a través de su código con las funciones Macro y __FILE__ __LINE__ C
  • aprender a utilizar el depurador -. Si su plataforma admite volcados de memoria, se puede utilizar la imagen del núcleo de encontrar dónde está el error

Otros consejos

printf escribe en la salida estándar, que está tamponada. A veces ese búfer no quede vaciada antes de que su programa se bloquea por lo que nunca se ve la salida. Dos maneras de evitar esto:

  1. Uso fprintf( stderr, "error string" ); desde stderr no está tamponada.
  2. añadir una llamada a fflush( stdout ); después de la llamada printf.

Como Neil y otros han dicho, el código escrito como está muy bien. Es decir, hasta que empiece a modificar el búfer que testChar puntos a.

"Al igual que en, una forma fácil / intuitiva para encontrar la línea de código que es un problema?"

Uso gdb (o cualquier otro depurador).

Para saber donde las fallas de su programa SEG se compilan con la opción -g (para incluir los símbolos de depuración) ejecutar la aplicación de gdb , se detendrá en la culpa seg.

A continuación, puede mirar traza inversa con el comando para ver bt momento en el que tienes la culpa seg.

ejemplo:

> gdb ./x
(gdb) r
Starting program: /proj/cpp/arr/x 
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
0x000019a9 in willfail () at main.cpp:22
22          *a = 3;
(gdb) bt
#0  0x000019a9 in willfail () at main.cpp:22
#1  0x00001e32 in main () at main.cpp:49
(gdb) 

La salida es amortiguada por defecto, esta falla se produce antes de la salida se escribe realmente en la salida estándar. Proveedores:

fprintf(stderr, "hello, world\n");

(stderr es sin búfer de forma predeterminada.)

Este código no debe segfault. No eres más que la asignación de un puntero a una cadena literal a una variable puntero. Las cosas serían diferentes si usted fuera, por ejemplo, utilizando strcpy para copiar cosas con un puntero no válido.

El mensaje no apareciendo puede ser debido a I / O tamponada. Imprimir un \n carácter de nueva línea o llame fflush para vaciar el búfer de salida.

Existen dos problemas. La primera es que el (original) código no segfault. Es perfectamente válido para asignar a esa constante a un puntero char cadena. Pero dejemos eso de lado por ahora y pretender que había puesto algo allí que lo haría violación de segmento.

A continuación, por lo general es una cuestión de tampones, el que está en la biblioteca de tiempo de ejecución C y la del propio sistema operativo. Es necesario para limpiar ellos.

La forma más sencilla de hacerlo era (en UNIX, no es del todo seguro sobre el fsync en Linux, sino que debe estar garantizado que este Wil pasar con el tiempo a menos que el propio sistema se cae):

printf ("DEBUG point 72\n"); fflush (stdout); fsync (fileno (stdout));

He hecho esto a menudo en UNIX y asegura que las bibliotecas de tiempo de ejecución C se vacían en UNIX (fflush) y los tampones de UNIX son sync'ed en el disco (fsync), útil si la salida estándar no es un terminal o dispositivo que están haciendo por un identificador de archivo diferente.

void* test;

printf("hello world");
test[5] = 234;

Su probable que "hola mundo" está siendo amortiguada por el sistema en algún lugar y no se imprime de inmediato a la pantalla. Su almacenados a la espera de una oportunidad para que cualquier proceso / hilo / lo que está a cargo de la escritura de pantalla puede tener la oportunidad de procesarlo. Y mientras que su espera (y posiblemente otros datos amortiguando a la salida) que eres la función está terminando. Se trata sobre el acceso ilegal y de segmentación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top