Erreur de bus dans le programme C sur la machine Unix

Je suis assez inexpérimenté avec C et je rencontre une “erreur de bus” que je ne peux pas comprendre la cause. Je n’avais jamais entendu parler de gdb mais je l’ai trouvé sur ce forum et j’ai essayé de l’utiliser sur mon programme de problèmes et j’ai obtenu la sortie suivante:

% gdb Proc1 GNU gdb 5.0

Cette GDB était configurée comme “sparc-sun-solaris2.8” …

(aucun symbole de débogage trouvé) …

(gdb) exécuter

Programme de démarrage: / home / 0 / vlcek / CSE660 / Lab3 / Proc1

(aucun symbole de débogage trouvé) …

(aucun symbole de débogage trouvé) …

(aucun symbole de débogage trouvé) …

Signal reçu du programme SIGSEGV, défaut de segmentation. 0x10a64 dans main ()

Je n’ai aucune idée de ce que cela signifie, cela signifie-t-il une erreur dans la ligne 10 de mon code? Si oui, la ligne 10 de mon code est simplement “int main ()” donc je ne suis pas sûr du problème … Quand j’essaie d’exécuter le programme, tout ce qu’il dit est “Erreur de bus” donc allez d’ici J’ai même essayé de mettre une printf juste après le main et cela n’imprime pas la chaîne, mais seulement une erreur de bus.

Voici mon code:

// Compilation Command: gcc -o Proc1 Proc1.c ssem.o sshm.o #include  #include  #include  #include "ssem.h" #include "sshm.h" // Code of Proc1 int main() {int i, internal_reg; int key1 = 111111, key2 = 222222, key3 = 333333, key4 = 444444; /* here create and initialize all semaphores */ int sem1 = sem_create(key1, 1); if (sem1 < 0) { perror("sem failed"); } int sem2 = sem_create(key2, 1); if (sem2 < 0) { perror("sem failed"); } int sem3 = sem_create(key3, 1); if (sem3 < 0) { perror("sem failed"); } int sem4 = sem_create(key4, 1); if (sem4 < 0) { perror("sem failed"); } /* here created: shared memory array Account of size 3 */ int *Account; int shmid = shm_get(123456, (void**) &Account, 3*sizeof(int)); if (shmid < 0) { perror("shm failed"); } Account[0]=10000; Account[1]=10000; Account[2]=10000; /* synchronize with Proc2, Proc3 and Proc4 (4 process 4 way synchronization)*/ for (i = 0; i < 1000; i++) { sem_signal(sem1); sem_signal(sem1); sem_signal(sem1); internal_reg = Account[0]; internal_reg = internal_reg - 200; Account[0] = internal_reg; /* same thing, except we're adding $100 to Account1 now... */ internal_reg = Account[1]; internal_reg = internal_reg + 200; Account[1] = internal_reg; if (i % 100 == 0 && i != 0) { printf("Account 0: $%i\n", Account[0]); printf("Account 1: $%i\n", Account[1]); } if (i == 300 || i == 600) { sleep(1); } sem_wait(sem2); sem_wait(sem3); sem_wait(sem4); } /* Here add a code that prints contents of each account and their sum after 100th, 200th, 300th, ...., and 1000th iterations*/ } /*in the code above include some wait and signal operations on semaphores. Do no t over-synchronize. */ 

Voici la documentation de ssem et sshm:

 /* * ssem.c * * Version 1.0.0 * Date : 10 Jan 2002 * */ #include  #include  #include  #include "ssem.h" #define PERMS 0600 static struct sembuf op_lock[1] = { 0, -1, 0 }; static struct sembuf op_unlock[1] = { 0, 1, IPC_NOWAIT }; int sem_create(int key,int initval) { int semid,i; semid = semget((key_t)key, 1, IPC_CREAT | PERMS); for(i=0;i<initval;i++) semop(semid,&op_unlock[0],1); return semid; } int sem_open(int key) { int semid; semid = semget(key,0,0); return semid; } int sem_wait(int semid) { return semop(semid,&op_lock[0],1); } int sem_signal(int semid) { return semop(semid,&op_unlock[0],1); } int sem_rm(int semid) { return semctl(semid, 0, IPC_RMID, 0); } /* * sshm.c * * Routines for Simpler shared memory operations * Version : 1.0.0. * Date : 10 Jan 2002 * */ #include  #include  #include  #include "sshm.h" #define PERMS 0600 int shm_get(int key, void **start_ptr, int size) { int shmid; shmid = shmget((key_t) key, size, PERMS | IPC_CREAT); (*start_ptr) = (void *) shmat(shmid, (char *) 0, 0); return shmid; } int shm_rm(int shmid) { return shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0); } 

Après avoir compilé Proc1.c avec l’indicateur -ggdb et exécuté gdb, j’ai obtenu ce qui suit:

Signal reçu du programme SIGSEGV, défaut de segmentation. 0x10a64 dans main () à Proc1.c: 36

36 Compte [0] = 10000

Pourquoi cela provoquerait-il une erreur de segmentation?

Après avoir changé la déclaration de compte en

 int *Account = 0; 

et en ajoutant

 printf("Account == %p\n", Account); 

avant le compte [0] = 10000;

Je reçois ce qui suit lors de l’exécution de Proc1:

 Account == ffffffff Bus error 

Afin d’obtenir des résultats plus sensibles de gdb, vous devriez comstackr votre programme avec l’option -ggdb . Cela inclura ensuite les informations de débogage (comme les numéros de ligne) dans votre programme.

Ce que vous voyez actuellement, c’est l’adresse mémoire ( 0x10a64 ) du compteur de programme. Cela ne vous aidera pas beaucoup, à moins que vous ne puissiez corréler vous-même les instructions d’assemblage que vous y trouverez avec une partie de votre programme C.

Il semble que vous shm_get correctement shm_get . Je pense que le concepteur de la bibliothèque a commis une terrible erreur en nommant la fonction de manière similaire à shmget .

C’est comme je le pensais. Le pointeur de Account se termine par une valeur non valide (aka 0xffffffff (aka (void *)(-1) )). La valeur (void *)(-1) indique généralement une sorte d’erreur, et elle est explicitement mentionnée dans la page de shmat de shmat . Cela indique que l’appel shmat à l’intérieur de la bibliothèque a échoué. Voici comment vous pouvez savoir si cela a échoué:

  if (Account == (void *)(-1)) { perror("shmat failed"); } Account[0] = 10000; // ... 

Maintenant, pourquoi cela a échoué est un mystère intéressant. Apparemment, l’appel shmget réussi.

Personnellement, je pense que System V IPC est fondamentalement obsolète à ce stade et que vous devriez éviter de l’utiliser si vous le pouvez.

En fonction de votre compilateur et de vos options de compilateur, vous pouvez rencontrer un problème d’alias car vous transmettez l’adresse de votre pointeur de Account . Ces anciennes interfaces ne sont pas en phase avec les règles d’anticrénelage modernes, ce qui signifie que l’optimiseur suppose que la valeur de Account ne changera pas.

Aussi, vous devriez obtenir l’argument de shm_get aussi proche que possible du type attendu. Essayez peut-être quelque chose comme ce qui suit.

 void volatile* shmRet; int shmid = shm_get(123456, (void**) &shmRet, 3*sizeof(int)); int *Account = shmRet; 

Je n’ai pas la même architecture, donc je ne connais pas le prototype exact de votre shm_get mais généralement, il est également shm_get d’utiliser des clés fixes pour ce type de fonctions. Il devrait y avoir une fonction qui vous renvoie une clé à utiliser dans votre application.