"Segmentation fault 11" crashing in for loop - c

I'm super new to C programming, only taking it for a required course in uni and finally getting done with my final project this week.
Problem is every time I run this code I get an error message that says "segmentation fault: 11" and I'm not sure what that means.
The code is supposed to run two-player race. Each player has a pre-determined "speed modifier", aka a number from 0-9. A random number from 1-10 is generated; if the speed modifier + the random number doesn't exceed 10, then the speed modifier is added and the car moves that total amount of "spaces". The whole race track is 90 "spaces".
Every time I run this code it works somewhat fine (more on that later) for one or two iterations, then gives out that error message. I normally don't ask for homework help online but I'm honestly so confused. Any help at all would be super appreciated.
Here is the relevant code:
Race (main) function:
int race(struct car cars[4], int mode)
{
/* Define variables. */
int endgame, i, x, y, first=-1, second=-1, randnum, spaces[]={};
char input[100];
/* Declare pointer. */
int *spacesptr=spaces;
for (i=0; i<mode; i++)
{
/* Array spaces will keep track of how many spaces a car has moved. Start each car at 0. */
spaces[i]=0;
}
/* Clear screen before race. */
system("cls");
/* Print message to indicate race has started. */
printf("\n3...\n2...\n1...\nGO!\n\n");
/* Open do while loop to keep race running until it is over. */
do
{
/* Conditions for two player mode. */
if (mode==2)
{
/* Run the next block of code once for each player. */
for (i=0; i<mode; i++)
{
/* Generate random integer from 1-10 to determine how many spaces the car moves. */
x=10, y=1;
randnum=(getrandom(x, y));
spaces[i]=spaces[i]+randnum;
/* Call function speedmod to determine if speedmodifier should be added. */
speedmod(cars, spaces, randnum);
/* Rank players. */
if (spaces[i]>89)
{
if (first==-1)
{
first=i;
}
else if (second==-1)
{
second=i;
}
}
}
}
...
/* Call function displayrace to display the race. */
displayrace(cars, spaces, mode);
/* Call function endgame to determine if the race is still going. */
endgame=fendgame(mode, spaces);
if (endgame==0)
{
/* Ask for player input. */
printf("Enter any key to continue the race:\n");
scanf("%s", input);
/* Clear screen before loop restarts. */
system("cls");
}
} while (endgame==0);
}
Random number function:
int getrandom(int x, int y)
{
/* Define variable. */
int randnum;
/* Use time seed. */
srand(time(0));
/* Generate random numbers. */
randnum=(rand()+y) % (x+1);
return randnum;
}
Add speed modifier function:
void speedmod(struct car cars[4], int spaces [], int go)
{
/* Declare pointer. */
int *spacesptr=spaces;
/* If the number of spaces plus the speed modifier is less than or equal to ten... */
if (spaces[go]+cars[go].speedmod<=10)
{
/* ...add the speed modifier to the number of spaces moved. */
spaces[go]=spaces[go]+cars[go].speedmod;
}
}
Display race function:
void displayrace(struct car cars[4], int spaces[], int mode)
{
/* Define variables. */
int i, j;
/* Declare pointers. */
int *spacesptr=spaces;
struct car *carsptr=cars;
/* Open for loop. */
for (i=0; i<mode; i++)
{
/* Print racecar number. */
printf("#%d\t", cars[i].carnumber);
/* For every space the car has moved... */
for (j=0; j<spaces[i]; j++)
{
if (j<=90)
{
/* ...print one asterisk. */
printf("*");
}
}
/* New line. */
printf("\n");
}
}
End game function:
int fendgame(int mode, int spaces[])
{
/* Define variables. */
int racers=0, endgame=0, i;
/* Declare pointer. */
int *spacesptr=spaces;
/* Open for loop. */
for (i=0; i<mode; i++)
{
/* If any of the racers have not yet crossed the finish line (90 spaces)... */
if (spaces[i]<=90)
{
/* ...then add to the number of racers still in the game. */
racers++;
}
}
/* If all the racers have crossed the finish line... */
if (racers==0)
{
/* ...then end the game. */
endgame=1;
}
return endgame;
}
Now to be more specific on the issue...it's messing up somewhere on the "for" loop in the race function. For some reason it doesn't actually go through each iteration of "i", specifically in this line:
spaces[i]=spaces[i]+randnum;
I know this because I put in printf statements to display the value of spaces[i] before and after; the first iteration of i works fine...but the second iteration actually uses spaces[i-1] instead and adds the randnum to that value?
And then, like I said, it crashes after one or two times of this...:-(
I know it's a lot but I'm hoping someone more experienced than I could spot the error(s) in this code for me! Please help!

I believe the first user above was correct in saying that the error is because there is no initial size declared for the array, but the solution is incorrect. You would have to allocate its size dynamically using malloc.
Also, I'd shorten spaces[i]=spaces[i]+randnum to just spaces[i] += randnum.

regarding: Problem is every time I run this code I get an error message that says "segmentation fault: 11" and I'm not sure what that means.
This means your program is trying to access memory that the application does not own.
For instance, a 'wild' pointer or uninitialized pointer or writing past the end of an array.

Thanks for the help. After a ton of tinkering around with this code I finally found the issue.
I was passing randnum to the speedmod function as if it were an index of the array spaces. I changed the function to the following, where num is the random number generated and go is the index:
void speedmod(struct car cars[4], int spaces [], int num, int go)
{
/* Declare pointer. */
int *spacesptr=spaces;
/* If the number of spaces plus the speed modifier is less than or equal to ten... */
if (num+cars[go].speedmod<=10)
{
/* ...add the speed modifier to the number of spaces moved. */
spaces[go]+=cars[go].speedmod;
}
}
Works perfectly now. Thanks for the help again.

you declare spaces[]={}, so it allocates a ptr that points to nothing. then you start writing all over it, which destroys probably your stack, your other variables, and whatever else is there -> undefined behavior.
you need to provide the memory to write to before you use it, for example spaces[1000]={}, ot however much you need.

Related

RNG Character Printing Function - More than one line of RNG characters per page? : C

So, I wrote a function (and an RNG function, which the aforementioned function calls) to print a random number of asterisks to the console window, until it hits 90 spaces. The asterisks represent the movement of a car, and the 90 spaces is the length of the track. The code I've included below prints a random number of asterisks until it hits 90 spaces, assuming the fnvMoveSpaces() function is called in main and the user presses a key to resume the loop after each system("PAUSE") until 90 spaces is hit.
My question is, looking at the provided code, how would I get four separate lines of totally independent RNG character printing on the same page of the console window? It needs to look like a legitimate race, on the same screen.
What I've tried:
1) Separate functions for each line, called in main:
Won't work, as they don't happen at the same time. Results in four different pages. I.e. the user has to press a key to get through system("PAUSE") until it hits 90 spaces, then the next function does the same, then the next, and the next. Also, if the loop/function call is outside of the fnvMoveSpaces() main loop, they don't print to the same page.
2) Putting four of the same for loops in the fnvMoveSpaces() function:
This prints four lines to the same screen, but they all move the same increment, because they are pulling from the same RNG value.
Basically, the RNG values for each line need to be totally independent of one another. Would having a different seed value for each line be the answer? I have no idea...
/* - - DEFINED - - */
// Constants of RNG for spaces moved
#define TRACK_LENGTH 90
#define MAX_MOVE_SPACES 10
#define MIN_MOVE_SPACES 1
// Assume fnvMoveSpaces call in main
// Function to create random number for car movement
int fniRandGenMove()
{
// Declare
int randInt;
// Initialize random seed
srand(time(NULL));
// Formula for RNG (1-10) based on global-defined numbers
randInt = (rand() % (MAX_MOVE_SPACES - MIN_MOVE_SPACES + 1) + MIN_MOVE_SPACES);
return (randInt);
}
void fnvMoveSpaces()
{
// Declare
int i;
int iMoveSum;
// Outer for loop to maintain the sum of asterisks
for(iMoveSum = 0; iMoveSum <= TRACK_LENGTH; iMoveSum += fniRandGenMove())
{
// Inner for loop to print asterisks
for(i = 0; i < iMoveSum; i++)
{
putchar('*');
}
// Newline for next line of asterisks
printf("\n");
/*
I'm assuming three more for loops... I tried a bunch of
combinations of things, even making new iMoveSums
(2, 3 and 4) and doing for loops.
But, no luck.
I should also not that making four separate functions for each
line of asterisks will not work, unless there is a way to call all
four at once in main. Separate functions results in separate screens
in the console window. In addition, if the four 'putchar' blocks
are not in the same loop as a whole, the first one will print, hit
90 spaces, then the second, etc... They aren't on the same screen.
*/
// System pause to wait for user
system("PAUSE");
// Clear screen
system("CLS");
}
}
Just to clarify, the current output of this in the console window is this:
**.....*
(Writing in a form of enumeration; no periods actually output.)
Until 90 spaces are hit, then the program closes. Also keep in mind that it prints in random increments each time the user presses a key after system("PAUSE"), until 90. So, not all the asterisks print at once.
What I want it to output is something like this:
*...**
*.........**
**........................*
**..............*
With each line randomly generating its own independent movement increment, until 90 spaces are hit.
Hope that helps.
Thanks,
Bagger
Okay, I got it worked out. Keep in mind that at some point in the near future, I intend to replace the structures with some file I/O. Also, fniRandGenMove is the same as in the question, just move the seed to main, so it only seeds once.
But it works perfectly... the 'cars' race across the console window! It's actually really neat.
void fnvMoveSpaces(int iAutoManual)
{
// Declare
int i, j;
// Declare structures
struct Car stCars[4];
stCars[0].iPosition = 0;
stCars[1].iPosition = 0;
stCars[2].iPosition = 0;
stCars[3].iPosition = 0;
stCars[0].iCarNumber = 1;
stCars[1].iCarNumber = 2;
stCars[2].iCarNumber = 3;
stCars[3].iCarNumber = 4;
struct Car furthestCar;
furthestCar.iPosition = 0;
furthestCar.iCarNumber = 0;
do
{
for(i = 0; i < 4; i++)
{
if(stCars[i].iPosition <= TRACK_LENGTH)
{
stCars[i].iPosition += fniRandGenMove();
}
printf("Car %d\n\t", stCars[i].iCarNumber);
for(j = 0; j < stCars[i].iPosition; j++)
{
printf("*");
}
if (stCars[i].iPosition > furthestCar.iPosition)
{
furthestCar.iPosition = stCars[i].iPosition;
furthestCar.iCarNumber = stCars[i].iCarNumber;
}
printf("\n");
}
system("PAUSE");
system("CLS");
} while(furthestCar.iPosition < TRACK_LENGTH);
printf("The winning car is #%d.\n", furthestCar.iCarNumber);
}

How to use isdigit() for a pin while loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This program accepts any four digit number as the pin , so i used a strlen() to find out whether the pin is has four characters, but I need to make sure that user enters four numbers, how do I use isdigit() before the loop and for the loop condition?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char pin [4];
printf("Please enter your pin : \n") ;
scanf("%4s" , &pin) ;
system("cls") ;
while (strlen(pin) != 4) {
count = count + 1 ;
if(count < 3){
printf("Invalid Pin \n") ;
printf("Please enter your pin again \n") ;
scanf("%4s", &pin) ;
system("cls");
}
else if (count == 3){
printf("Sorry you can't continue , Please contact your bank for assistance !") ;
return 0 ;
}
}
There are so many issues with this code I may not have covered every one of them in this answer:
Where is your main function? You can't have code outside a function; that doesn't work. C code other than global variable declarations, assignments to constant values, typedefs, struct and enum definitions, must go in a function. In your case you probably want the main function to house the code starting at line 6.
When calling scanf with a string argument, don't take the address of the string - the array is a reference in and of itself.
Calling strlen(pin) before any value has been copied into pin is 100% undefined behavior. Since the memory is uninitialized the strlen function will keep looking for a null character and possibly go out of the array bounds.
C strings are null-terminated. When you declare a string intended to hold n characters, you need to declare the array with a size of n+1 to have room for the null character.
First to answer your question
I would write a helper function 'validatePin' which would check the pin length and validate that the pin is a numeric pin, you can extend this function to do any other validation you require. It might look something like the following
const int PIN_OK = 0;
const int PIN_INVALID_LEN = -1;
const int PIN_INVALID_CHARS = -2;
int validatePin(const char *pin)
{
// Valdiate PIN length
if (strlen(pin) != 4) return PIN_INVALID_LEN;
// Validate PIN is numeric
for (int i = 0; i < 4; ++i)
{
if (!isdigit(pin[i])) return PIN_INVALID_CHARS;
}
return PIN_OK;
}
Then you can adjust your while loop to look something like the following
while (validatePin(pin) != PIN_OK)
{
....
}
Other points regarding your code.
Your char buffer used for scanf does not account for the null terminator. You need to increase the buffer size.
The char array is already giving you the address of the buffer, there is no need to use & to take the address of the char array in scanf.
I have not run your code, so there might be other issues that I missed at first glance.
There are a number of ways to go about doing what you need to do. You can either check your input length, or just validate what it is you have read, your choice. One approach would be:
#include <stdio.h>
#include <ctype.h>
enum { TRIES = 3, NPIN };
int main (void) {
char pin[NPIN+1] = "";
size_t tries = 0, pinok = 0;
for (; tries < TRIES; tries++) { /* 3 tries */
printf ("Please enter your pin : ");
if (scanf (" %4[^\n]%*c", pin) == 1) { /* read pin */
pinok = 1;
size_t i;
for (i = 0; i < NPIN; i++) /* validate all digits */
if (!isdigit (pin[i]))
pinok = 0;
if (pinok) /* if pin good, break */
break;
}
}
if (!pinok) { /* if here and not OK, call bank */
fprintf (stderr, "Sorry you can't continue, Please contact "
"your bank for assistance.\n") ;
return 1;
}
printf ("\n correct pin : %s\n\n", pin); /* your pin */
return 0;
}
(note: to protect against an excessively long string entered at one time, you should empty stdin at the end of the outer for loop each iteration)
Example Use/Output
Failed case:
$ ./bin/pin
Please enter your pin : a555
Please enter your pin : 555a
Please enter your pin : 55a5
Sorry you can't continue , Please contact your bank for assistance.
Successful case:
$ ./bin/pin
Please enter your pin : 2345
correct pin : 2345
Look it over an let me know if you have any questions.

How to store keys of associative array in C implemented via hcreate/hsearch by value (not by reference)?

Using associative arrays implented via the POSIX hcreate/hsearch functions (as described here, I struggled some unexpected behaviour finding keys I've never entered or the other way around.
I tracked it down to some instance of store-by-reference-instead-of-value.
This was surprising to me, since in the example uses string literals as keys:
store("red", 0xff0000);
store("orange", 0x123456); /* Insert wrong value! */
store("green", 0x008000);
store("blue", 0x0000ff);
store("white", 0xffffff);
store("black", 0x000000);
store("orange", 0xffa500); /* Replace with correct value. */
Here is an MWE that shows my problem:
#include <inttypes.h> /* intptr_t */
#include <search.h> /* hcreate(), hsearch() */
#include <stdio.h> /* perror() */
#include <stdlib.h> /* exit() */
#include <string.h> /* strcpy() */
void exit_with_error(const char* error_message){
perror(error_message);
exit(EXIT_FAILURE);
}
int fetch(const char* key, intptr_t* value){
ENTRY e,*p;
e.key=(char*)key;
p=hsearch(e, FIND);
if(!p) return 0;
*value=(intptr_t)p->data;
return 1;
}
void store(const char *key, intptr_t value){
ENTRY e,*p;
e.key=(char*)key;
p = hsearch(e, ENTER);
if(!p) exit_with_error("hash full");
p->data = (void *)value;
}
void main(){
char a[4]="foo";
char b[4]="bar";
char c[4]="";
intptr_t x=NULL;
if(!hcreate(50)) exit_with_error("no hash");
store(a,1); /* a --> 1 */
strcpy(c,a); /* remember a */
strcpy(a,b); /* set a to b */
store(a,-1); /* b --> -1 */
strcpy(a,c); /* reset a */
if(fetch(a,&x)&&x==1) puts("a is here.");
if(!fetch(b,&x)) puts("b is not.");
strcpy(a,b); printf("But if we adjust a to match b");
if(fetch(a,&x)&&x==-1&&fetch(b,&x)&&x==-1) puts(", we find both.");
exit(EXIT_SUCCESS);
}
Compiling and executing above C code results in the following output:
a is here.
b is not.
But if we adjust a to match b, we find both.
I will need to read a file and store a a large number of string:int pairs and then I will need to read a second file to check an even larger number of strings for previously stored values.
I don't see how this would be possible if keys are compared by reference.
How can I change my associative array implementation to store keys by value?
And if that's not possible, how can I work around that problem given the above use case?
edit:
This question just deals with keys entered but not found.
The opposite problem also appears and is described in detail in this question.
edit:
It turned out that store() needs to strdup() key to fix this and another problem.
I found out that by using the same variable for storage & lookup, I can actually retrieve all the values in the array:
void main(){
char a[4]="foo";
char b[4]="bar";
char c[4]="baz";
char t[4]="";
intptr_t x=NULL;
if(!hcreate(50)) exit_with_error("no hash");
strcpy(t,a); store(t, 1); /* a --> 1 */
strcpy(t,b); store(t,-1); /* b --> -1 */
strcpy(t,c); store(t, 0); /* c --> 0 */
if(!fetch(a,&x)) puts("a is not here.");
if(!fetch(b,&x)) puts("Neither is b.");
if( fetch(c,&x)) puts("c is in (and equal to t).");
strcpy(t,a); if(fetch(t,&x)&&x== 1) puts("t can retrieve a.");
strcpy(t,b); if(fetch(t,&x)&&x==-1) puts("It also finds b.");
strcpy(t,c); if(fetch(t,&x)&&x== 0) puts("And as expected c.");
exit(EXIT_SUCCESS);
}
This results in the following output:
a is not here.
Neither is b.
c is in (and equal to t).
t can retrieve a.
It also finds b.
And as expected c.
However, I still don't understand why this is happening.
Somehow it seems the key needs to be at the same location (reference) and contain the same content (value) to be found.

Getting stange error with strings

I'm writing a program in C for my beaglebone black to manipulate the gpio pins. This is a very crude program but its just a "beta" if you will. Just to get it up and running. My problem is that I have two character arrays. One holding a command to be passed to the system() function and another holding the path of the file that I am going to be editing, it goes to the fopen function. These character arrays are manipulated to change two numbers depending on what is passed to them from the calling function. For some reason the filename character array is being concatenated with the command. I'm skimming through the program but i don't see any obvious errors.
Here is my code
/*
* gpio.c
*
* Created on: Aug 26, 2014
* Author: Christian Macias
*
* Description: This will control your GPIO (General Purpose IO) pins on the beagle bone. Please
* ensure you are on a kernel that supports device trees.
*
* Usage: gpio(PIN, Value "1" or "0", Inverted? "0" false or "1" for true)
*
* The return value is 0 for success and -1 for failure
*
* GO UTEP!!
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int gpio(int pin, int value, int inv)
{
int sucfail=0;
int pinInt1, pinInt2=-1;
int counterOne=NULL;
char filename[28]= "/sys/class/gpio/gpio00/value";//27 characters
/*
* Checks if file is within the gpio pin range.
*/
if(pin<0 || pin>=99)
{
fprintf(stderr, "\n%s\n\t%s\n\t%s\n", "Error in gpio.c(GPIO): ", "The gpio pin selected is not "
"within the availabilty of the app", "Please select a pin from 0-99");
return -1;
}
/*
* checks to see if value is boolean aka 1 or 0
*/
if(value<0 || value>1)
{
fprintf(stderr, "\n%s\n\t%s\n\t%s", "Error in gpio.c(GPIO): ", "The Selected value is invalid", "Please"
" select a 1 or a 0");
return -1;
}
/*
* Writes the pin to a file so that it can used later
*/
FILE *PINWRITE;
PINWRITE=fopen("pinWRITE", "w+");
fprintf(PINWRITE,"%i", pin);
fclose(PINWRITE);
/*
* This section will check for pre-existence of the the PIN file to prevent errors. or
* opens it if it doesnt exist.
* First it will set up the filenames
*/
PINWRITE=fopen("pinWRITE","r");
fscanf(PINWRITE, "%1i%1i", &pinInt1, &pinInt2);//Checks the pin and sets each digit to its according variable
fclose(PINWRITE);
filename[20]='0'+pinInt1;
if(pinInt2==-1)//If it is a one digit pin, it will move the letters to fit the file name correctly and remove one of the digits
{
for(counterOne=21;counterOne<28;counterOne++)
{
filename[counterOne]=filename[counterOne+1];
}
filename[27]='\0';
}
else//If two digits it will just change the second digit
{
filename[21]='0'+pinInt2;
}
FILE *PINVALUE;//FILE pointer to the files with the value
PINVALUE=fopen(filename,"w+");
/*
* At this point the the actual checking and creation occurs
*/
char exportCommand[32]="echo 00 > /sys/class/gpio/export";//31 characters
if(PINVALUE==NULL)
{
//this runs if the file didnt exist.
exportCommand[5]='0'+pinInt1;
if(pinInt2==-1)//If it is a one digit pin, it will move the letters to fit the file name correctly and remove one of the digits
{
for(counterOne=6;counterOne<32;counterOne++)
{
exportCommand[counterOne]=exportCommand[counterOne+1];
}
exportCommand[31]='\0';
}
else//If two digits it will just change the second digit
{
exportCommand[6]='0'+pinInt2;
exportCommand[32]='\0';
}
system(exportCommand);
printf("\n%s\n", exportCommand);
printf("\n%s\n", filename);
PINVALUE=fopen(filename,"w+");
}
if(PINVALUE==NULL)
{
fprintf(stderr,"\n%s\n\t%s", "Error in gpio.c(GPIO)", "The PINVALUE (.../gpioXX/value) could not be opened");
return -1;
}
/*
* Some pins may be set up backward... on is off and off is on. To correct this we must adjust a file...
* This takes to long and i dont have the time for it so i'm doing a hot fix... sorry but its 11 and i have
* school tomorrow. The correction process it too long and i want to finish today :)
*/
if(inv==1 && value==1)
{
value=0;
}
else if(inv==1 && value==0)
{
value=1;
}
/*
* At this point the file is set up and ready to be written to.
* We will write the value now and close it.
*/
fprintf(PINVALUE, "%i", value);
fclose(PINVALUE);
return sucfail;
}
You are underestimating the length of string literals you want to copy into arrays, leaving no space for the nul terminator. For example, here
char filename[28]= "/sys/class/gpio/gpio00/value"; //27 characters
the literal actually has 28+1 characters (28 visible, plus a nul terminator).
You need to make the array of size 29. You can do this explicitly,
char filename[29] = "/sys/class/gpio/gpio00/value";
or implicitly:
char filename[] = "/sys/class/gpio/gpio00/value";
Similarly here, where you need the array to be of length 33:
char exportCommand[32]="echo 00 > /sys/class/gpio/export";
There may well be other errors. I would start by fixing those first. It will make finding the other ones easier.

Return not ending method in c

edit - i figured out the arithmetic error but I still have the return error
For some reason my program is giving me two errors. First error is that the "return" at the end of each of my methods() are not ending the method and bring me back to main. My second question is at line 23 where pfNum = mainSize/pageSize; is giving me a "SIGFPE, arithmetic exception" not sure why both of these are occuring can anyone help me out?
Thanks
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Define page table as dynamic structure containing virtual page and page frame
and initialize variable as pointer to structure */
struct table{
int vp;
int pf;
}*pageTable = NULL;
/* Declare global var's */
int mainSize,pageSize,policy,pfNum;
/**********************************************************************/
void option1(){
/* Declare local var's */
int k;
/* Prompt for main memory size, page size, and replacement policy */
printf("Enter main memory size(words): ");
scanf("%d",&mainSize);
printf("Enter page size(words/page): ");
scanf("%d",&pageSize);
printf("Enter replacement policy(0=LRU, 1=FIFO): ");
scanf("%d",&policy);
pfNum = mainSize/pageSize;
/* Allocate and initialize page table based on number of entries */
pageTable = malloc(pfNum *sizeof(pageTable));
for(k=0;k<pfNum;k++){
pageTable[k].vp=-1;
pageTable[k].pf=k;
}
return;
}
/**********************************************************************/
void option2(){
/* Declare local var's */
int va,page,offset,i=0,temp;
/* Prompt for virtual address */
printf("Enter virtual memory address to access: ");
scanf("%d",&va);
/* Translate virtual mem addr to virtual page and offset*/
page = va/pageSize;
offset = va%pageSize;
/* Check for end of table, unallocated entry, or matched entry in table
and update table appropriately; while none of three cases, keep looping */
while(i<pfNum && pageTable[i].vp!=1 && pageTable[i].vp!=page)
i++;
if(i<=pfNum){
int j;
temp = pageTable[0].pf;
for(j=1;j<pfNum;j++)
pageTable[j-1]=pageTable[j];
pageTable[j].vp=page;
pageTable[j].pf=temp;
printf("Page Fault!");
}
else if(pageTable[i].vp==-1){
pageTable[i].vp = page;
printf("Page fault!");
}
else if(pageTable[i].vp==page){
temp = pageTable[i].pf;
int l,address;
for(l=i+1;l<pfNum-1;l++)
pageTable[l-1]=pageTable[l];
pageTable[l].vp = page;
pageTable[l].pf = temp;
address = (temp*pageSize)+offset;
printf("Virtual address %d maps to physical address %d",va,address);
}
return;
}
/**********************************************************************/
void option3(){
/* Declare local var's */
int u;
for(u=0;u<pfNum;u++ && pageTable[u].vp!=-1)
printf("VP %d --> PF %d",pageTable[u].vp,pageTable[u].pf);
/* Print out each valid virtual page and page frame pair in table */
return;
}
/**********************************************************************/
int main(){
/* Declare local var's */
int choice;
/* Until user quits, print menu of options, prompt for user input, and select appropriate option */
printf("/n");
printf("Virtual memory to Main memory mapping:\n");
printf("--------------------------------------\n");
printf("1) Set parameters\n");
printf("2) Map virtual address\n");
printf("3) Print page table\n");
printf("4) Quit\n");
printf("\n");
printf("Enter Selection: ");
scanf("%d",&choice);
printf("\n");
while(choice!=4){
if(choice==1)
option1();
else if(choice==2){
option2();
}
else if(choice==3)
option3();
}
printf("Goodbye. Have a nice day.");
return 1;
}
The "SIGFPE, arithmetic exception" exception is most likely caused by division by zero.
One problem is that once you've made your initial choice, nothing changes choice again, so the program goes around the loop, executing your initial choice (possibly doing nothing at all, since you don't validate for zero, negative choices, or values greater than four). This might give the appearance that your functions "don't return" but actually they do return; they just get called again almost immediately.
You probably need to prompt for a new choice each time around the loop, which suggests a function to prompt and return the choice which you call from a while loop.
You have at least one "/n" where you probably intended "\n". Your farewell message is missing its newline; so are a number of other messages (such as the "Page Fault!" messages). You don't check that your input functions were successful. You don't check that the memory allocation was successful.
Your SIGFPE probably comes from division by zero; print the values you're processing before you execute the division.

Resources