I've looked over this about 15 times by now to no avail. I cannot understand why this is seg faulting? It doesn't even get to the "print" statement which makes no sense. the error codes actually do work tho (when I dont have a shared memory present) I have a load.c program but it works perfectly (im 100% sure of this)
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include "header.h"
//BEGIN MAIN FUNCTION
main()
{
int id; //ID to data shmem
struct StudentInfo *infoptr; //ptr to data
int found = 0; //found 'boolean'
char input[15]; //user input buffer
struct StudentInfo *beginptr; //ptr to beginning of data
int rcid; //Read count ID to shmem
int *rcptr; //RC ptr
int sema_set; //ID to shared semaphores
//Find the shmem at our ID
id = shmget(KEY,SEGSIZE,0);
if(id < 0)
{
perror("Query: shmget failed");
exit(1);
}
//set the ptr to our shared mem and attach to program
infoptr = (struct StudentInfo *)shmat(id,0,0);
if(infoptr <= (struct StudentInfo *)(0))
{
perror("Query: shmat failed");
exit(1);
}
//Get our RC in shared memory
rcid = shmget(RCKEY,READCOUNT,0);
if(rcid < 0)
{
perror("Query: shmget failed");
exit(1);
}
//Set ptr to shmem and attach to process
rcptr = (int*)shmat(rcid,0,0);
if(rcptr <= (int*)(0))
{
perror("Print: Shmat failed");
exit(1);
}
//Get semaphores
sema_set = semget(SEMA_KEY,NUM_SEMAPHS,0);
if(sema_set < 0)
{
perror("Query: Semget failed");
exit(1);
}
//Set program to queue up to wait
Wait(sema_set,1);
//Increment the read counter
*rcptr += 1;
//If we are the first reader, stop writers
if(*rcptr == 1)
Wait(sema_set,0);
//Signal readers
Signal(sema_set,1);
//Set our begin ptr
beginptr = infoptr;
//Begin user input loop
while(1)
{
//Ask user for input IT DOESN"T EVEN GET TO HERE <--
printf("Please input a student ID :");
scanf("%s",input);
//While the record is not found search
while(strcmp(infoptr->Name,"")!=0 && found != 1)
{
//If record found, print the record
if((strncmp(input,infoptr->ID,9)) == 0)
{
//Set found
found = 1;
printf("\n%s\n",info开发者_开发技巧ptr->Name);
printf("%s\n",infoptr->telNumber);
printf("%s\n",infoptr->Address);
printf("%s\n\n",infoptr->ID);
}
else
infoptr++;
}
//If not found, print error message
if(found == 0)
printf("Record not found.\n");
//Wait on readers
Wait(sema_set,1);
//Decrement
*rcptr--;
//If no readers left
if(*rcptr == 0)
Signal(sema_set,0); //Signal writers
//Signal readers
Signal(sema_set,1);
exit(0);
}
}
HEADER
#define KEY ((key_t)(11111)) /*change it to last five digits of your SSN*/
#define SEGSIZE sizeof(struct StudentInfo)
#define NUM_SEMAPHS 2
#define SEMA_KEY ((key_t)(1111)) /* change this to last four digits of SSN */
#define READCOUNT sizeof(int) //Set the size of shmem for read count
#define RCKEY ((key_t)(4003)) //Set the key of the shmem for RCount
//Struct student info
struct StudentInfo{
char Name[20];
char ID[15];
char Address[50];
char telNumber[15];
};
//Checks the semaphore whether or not to wait
void Wait(int semaph, int n);
//Signals that it's ok to run
void Signal(int semaph, int n);
//Gets the semaphore information
int GetSemaphs(key_t k, int n);
Your problem might come from your use of shmat
. In C, never cast the return type of such a function. That you felt the need for it probably means that you had a spurious error message that came from the fact that you are missing the "sys/shm.h" header.
What happens in such cases is that gcc takes the return type for an int
, usually a 32 bit quantity, and re-interprets it as a pointer. So the upper half of your address that shmat
gives you is lost.
As a general rule, don't cast away problems. Cast are rarely needed in C if all your headers are properly written. Casting the return type of a system function is almost always wrong.
Valigrind and GDB are your friend
Please provide the entire code so we can compile it and help you out. Staring at source isn't a magic approach to debuggin :)
Ensure you are compiling with the debugging options (-g etc) on your compiler.
Otherwise, checkout valgrind's memcheck. When you have your compiled program, run:
valgrind ./myprogram
And you may get output similar to the following:
==584== Use of uninitialised value of size 8
==584== at 0x400480: segfaultme (p.c:6)
==584== by 0x40049B: main (p.c:13)
==584==
==584== Invalid write of size 4
==584== at 0x400480: segfaultme (p.c:6)
==584== by 0x40049B: main (p.c:13)
==584== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==584==
==584==
==584== Process terminating with default action of signal 11 (SIGSEGV)
==584== Access not within mapped region at address 0x0
==584== at 0x400480: segfaultme (p.c:6)
==584== by 0x40049B: main (p.c:13)
==584== If you believe this happened as a result of a stack
==584== overflow in your program's main thread (unlikely but
==584== possible), you can try to increase the size of the
==584== main thread stack using the --main-stacksize= flag.
==584== The main thread stack size used in this run was 10485760.
Crack out GDB with:
gdb ./myprog
then enter rreturn
And you will get some more information on exactly where the segfault occurs:
(gdb) r
Starting program: /home/aiden/tmp/a.out
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400480 in segfaultme (p=0x0) at p.c:6
6 *p = 22;
Missing separate debuginfos, use: debuginfo-install glibc-2.11.2-1.x86_64
(gdb) bt
#0 0x0000000000400480 in segfaultme (p=0x0) at p.c:6
#1 0x000000000040049c in main () at p.c:13
Entering btreturn will give you a backtrace too. In the above example we can see that line 6 of p.c
in segfaultme()
where I dereference p
is the problem, and it shows segfaultme()
was called by main()
.
Hope this helps! Remember to get as much exposure to tools that help you!
精彩评论