Question

Comme beaucoup de jeunes programmeurs font, j'ai appris l'utilité d'insérer de nombreuses déclarations d'impression à console de « ici1 », « ici2, » et ainsi de suite à différents points de code pour savoir quand mes programmes vont mal tourné. Cette technique brute de débogage de force m'a sauvé de nombreuses fois tout au long de mes études CS. Cependant, quand j'ai commencé la programmation en C, je suis tombé sur un problème intéressant. Si je devais essayer de courir

void* test;

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

Bien sûr, je reçois une erreur de segmentation pour ne pas malloc'ing mémoire pour testChar. Cependant, on pourrait penser logiquement que « bonjour monde » serait imprimé avant que le défaut de seg se produit, puisque c'est le flux du code, mais dans mon expérience, il est toujours le cas que la faute de seg arrive en premier, et « Bonjour tout le monde "n'est imprimé à la console du tout. (Je ne suis pas en mesure de tester cet exemple précis, mais j'ai couru dans ce genre de situation de fois avec gcc sur une boîte Linux.) Je suppose que cela a à faire avec le compilateur réarranger certaines choses et / ou printf en utilisant une sorte de tampon qui est chassé de manière asynchrone et donc ne pas être immédiat. Ceci est tout à la spéculation de ma part parce que je ne sais vraiment pas pourquoi il arrive. Dans une autre langue que je l'ai utilisé, quel que soit le problème le « testChar = ... » ligne a provoqué, le « Bonjour tout le monde » serait encore imprimé, et je ne pouvais donc déterminer où le problème est.

Ma question est pourquoi cela se produit quand je suis programmation C? Pourquoi pas le monde bonjour d'abord imprimé? Et d'autre part, est-il une meilleure technique de débogage de programmation C que ce qui fait la même chose de base? Comme dans, un moyen facile / intuitive pour trouver la ligne de code qui est un problème?

Edit: J'ai donné un exemple de travail par accident haha. Ce que je devrait maintenant provoquer une erreur de segmentation. Il est drôle comment généralement quand je ne pas veux un segfault je reçois un, et maintenant quand je voulais vraiment que j'écrit le code légal!

Était-ce utile?

La solution

Le code affiché est parfaitement légal et ne doit pas provoquer une erreur de segmentation - il n'y a pas besoin de quoi que ce soit malloc. Votre problème doit se situer quelque part ailleurs -. S'il vous plaît poster le plus petit exemple de code qui provoque le problème

Modifier Vous avez maintenant modifié le code pour avoir un sens tout à fait différent. Pourtant, la raison pour laquelle « Bonjour tout le monde » n'est pas affiché est que le tampon de sortie n'a pas été vidées. Essayez addinig

fflush( stdout );

après la printf.

En ce qui concerne la localisation de la source du problème que vous avez deux choix:

  • saupoudrer généreusement printfs par votre code en utilisant les macros __FILE__ et __LINE__ C
  • apprendre à utiliser votre débogueur -. Si votre plate-forme prend en charge les décharges de base, vous pouvez utiliser l'image de base pour trouver où l'erreur est

Autres conseils

printf écrit à stdout, qui est tamponne. Parfois, ce tampon ne soit pas vidé avant que votre programme se bloque si vous ne voyez jamais la sortie. Deux façons d'éviter ceci:

  1. utilisation fprintf( stderr, "error string" ); depuis stderr ne tamponne.
  2. ajouter un appel à fflush( stdout ); après l'appel de printf.

Comme Neil et d'autres ont dit, le code tel qu'il est écrit est très bien. C'est, jusqu'à ce que vous commencez à modifier le tampon qui testChar points.

« Comme, un moyen facile / intuitive pour trouver la ligne de code qui est un problème? »

Utiliser gdb (ou tout autre débogueur).

Pour trouver où les défauts de votre programme vous compilent avec option -g (pour inclure des symboles de débogage) exécuter votre application à partir de gdb , il arrêtera sur la faute seg.

Vous pouvez alors regarder avec backtrace commande bt pour voir à quel point vous avez la faute de seg.

exemple:

> 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 sortie est tamponne par défaut, le segfault se produit avant que la sortie est effectivement écrit sur la sortie standard. Essayez:

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

(stderr est tamponnée par défaut.)

Ce code ne doit pas segfault. Vous êtes juste attribuer un pointeur sur une chaîne littérale à une variable de pointeur. Les choses seraient différentes si vous étiez par exemple en utilisant strcpy pour copier des trucs avec un pointeur non valide.

Le message n'apparaît peut être due à des E / S en mémoire tampon. Imprimer un caractère de nouvelle ligne \n ou appelez fflush pour vider le tampon de sortie.

Vous avez deux problèmes. La première est que votre code (original) ne sera pas segfault. Il est parfaitement valide pour attribuer à cette chaîne constante à un pointeur char. Mais laissons cela de côté pour l'instant et vous faites semblant avait mis quelque chose que serait segfault.

Ensuite, il est généralement une question de tampons, celui de la bibliothèque d'exécution C et celle du système d'exploitation lui-même. Vous devez les rincer.

La meilleure façon de le faire était (sous UNIX, pas tout à fait certain de la fsync sous Linux, mais vous devez être garanti que ce wil arriver à terme à moins que le système lui-même descend):

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

Je l'ai fait souvent sous UNIX et il assure que les bibliothèques d'exécution C sont vidées à UNIX (fflush) et les tampons UNIX sont sync'ed sur le disque (fsync), utile si stdout est pas un dispositif terminal ou vous le faisons pour une poignée de fichier.

void* test;

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

Il est probable que « Bonjour tout le monde » est tamponnées par le système quelque part et n'est pas immédiatement imprimé à l'écran. Son CONSERVE attendant une chance pour tout processus / fil / tout ce qui est en charge de l'écriture de l'écran peut avoir une chance de traiter. Et alors que son attente (et éventuellement d'autres données en mémoire tampon de sortie), vous êtes la fonction de finition. Il est sur l'accès illégal et segfaults.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top