开发者

Bus error in C Program on Unix machine

开发者 https://www.devze.com 2023-02-12 06:28 出处:网络
I\'m fairly unexperienced with C and am running into a \"Bus error\" that I cannot understand the cause of. I had never heard of gdb but came across it on this forum and tried using it on my problem p

I'm fairly unexperienced with C and am running into a "Bus error" that I cannot understand the cause of. I had never heard of gdb but came across it on this forum and tried using it on my problem program and got the following output:

% gdb Proc1 GNU gdb 5.0

...

This GDB was configured as "sparc-sun-solaris2.8"...

(no debugging symbols found)...

(gdb) run

Starting program: /home/0/vlcek/CSE660/Lab3/Proc1

(no debugging symbols found)...

(no debugging symbols found)...

(no debugging symbols found)...

Program received signal SIGSEGV, Segmentation fault. 0x10a64 in main ()

I have no idea what this means, is that saying there's an error in line 10 in my code? If so, line 10 in my code is merely "int main()" so I'm not sure the issue there... When I try running the program all it says is "Bus error" so I'm not sure where to go from here. I even tried putting a printf right after main and it doesn't print the string, only gives me a Bus error.

Below is my code:

// Compilation Command: gcc -o Proc1 Proc1.c ssem.o sshm.o

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#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 = se开发者_开发技巧m_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. */

Here is the documentation for ssem and sshm:

/*
 * ssem.c
 * 
 * Version 1.0.0
 * Date : 10 Jan 2002
 *
 */


#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>

#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 <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>

#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);

}

After compiling Proc1.c with the -ggdb flag and running gdb I got the following:

Program received signal SIGSEGV, Segmentation fault. 0x10a64 in main () at Proc1.c:36

36 Account[0]=10000

Why would this cause a segmentation fault?

After changing the declaration of Account to

int *Account = 0;

and adding

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

before Account[0] = 10000;

I get the following upon running Proc1:

Account == ffffffff
Bus error


In order to get more sensible results from gdb you should compile your program with the -ggdb option. This will then include debugging information (like line numbers) into your program.

What you are currently seeing is the memory address (0x10a64) of the program counter. This will not help you very much unless you can correlate the assembly instructions you find there with a part of your C program yourself.

It looks like you are using shm_get properly. I think the library designer has made a terrible mistake in naming the function so similarly to shmget.

It's just as I thought. The Account pointer is ending up with an invalid value (aka 0xffffffff (aka (void *)(-1))) in it. The value (void *)(-1) generally indicates some sort of error, and it is explicitly mentioned in the manpage for shmat. This indicates that the shmat call inside the library failed. Here is how you can tell if it failed:

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

Now, why it failed is an interesting mystery. Apparently the shmget call succeeded.

Personally, I think System V IPC is basically deprecated at this point and you should avoid using it if you can.


Depending on your compiler and your compiler options you might encounter an aliasing problem because your are casting the address of your Account pointer. These oldish interfaces are not in phase with modern antialiasing rules, meaning that the optimizer supposes that the value of Account wouldn't change.

Also you should get the argument for shm_get as close as possible to the expected type. Try perhaps something like the following.

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

int *Account = shmRet;

I don't have the same architecture, so I don't know the exact prototype of your shm_get but usually it is also a bad idea to use fixed keys for this type of functions. There should be some function that returns you some key to use in your application.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号