We help IT Professionals succeed at work.

Help avoiding segmentation fault

JeebusFnChrist
on
378 Views
Last Modified: 2010-04-15
I just finished writing a program that compiles properly. However, when I run the program, after I give input of either a string or an integer (I have included the code so you'll know what I'm talking about) the program gives me the error "Segmentation Fault (core dumped)". I'll include all my functions just in case they would affect this in anyway, but I'm sure the problem is in my main function. Any help fixing this error is greatly appreciated.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE *f1;

void loadFile(char* filename);
void listAllCustomers();
void listAllAccountsForCustomer(int id);


struct Bank {
  char* name;
  struct Customer* list;};
struct Customer {
  int ID;
  char* name;
  char* address;
  char* LoginName;
  char* Password;
  struct Account* list;
  struct Customer* next;
  struct Customer* last;};
struct Account {
  int num;
  char* type;
  float balance;
  float rate;
  struct Account* next;};

struct Bank bank;

main(){

char menu;
int cust;
char *filename;
filename=malloc(80*sizeof(char));
while (menu != '4'){
  printf("Please make your selection: \n");
  printf("1. Load file \n");
  printf("2. List all customers \n");
  printf("3. List all accounts for a customer \n");
  printf("4. Exit \n");
  menu = getchar();
  switch (menu) {
    case '1':
      printf("Please enter the name of the file to open: \n");
      scanf("%s", filename);
      loadFile(filename);
      break;
    case '2':
      listAllCustomers();
      break;
    case '3':
      printf("Enter the ID of the customer to list accounts for: \n");
      scanf("%d", &cust);
      listAllAccountsForCustomer(cust);
      break;
    }      
}
}

void loadFile(char* filename){
f1 = fopen(filename, "r");
char *buffer;
struct Customer *head=bank.list;
struct Customer *hold = head;
struct Account *temp=head->list;
int num;
int num2;
fgets(buffer, sizeof(buffer), f1);
while (strcmp(buffer, "END") != 0){
if (strcmp(buffer, "BANK") == 0){
  fgets (buffer, sizeof(buffer), f1);
  bank.name = buffer;}
if (strcmp(buffer, "CUSTOMERS") == 0){
  fgets (buffer, sizeof(buffer), f1);
  while (strcmp(buffer, "") != 0){
    num=atoi(strtok(buffer, ":"));      
    if (head==NULL){
      head->ID=num;
      head->name=strtok(NULL, ":");
      head->address=strtok(NULL, ":");
      head->LoginName=strtok(NULL, ":");
      head->Password=strtok(NULL, "\n");
      }
    else {
      if (num>hold->ID && hold->next==NULL){
        hold->next->ID=num;
        hold->next->name=strtok(NULL, ":");
      hold->next->address=strtok(NULL, ":");
      hold->next->LoginName=strtok(NULL, ":");
      hold->next->Password=strtok(NULL, "\n");
          hold->next->last=hold;
      }
    else {
      if (num<hold->ID && hold->last==NULL){
      hold->next=hold;
      hold->ID=num;
      hold->name=strtok(NULL, ":");
      hold->address=strtok(NULL, ":");
      hold->LoginName=strtok(NULL, ":");
      hold->Password=strtok(NULL, "\n");
      }
    else {
       if (num>hold->ID){
        while(num>hold->ID && hold->next!=NULL){
         hold=hold->next;
         }         
         if (hold->next==NULL){
         hold->next->ID=num;
         hold->next->name=strtok(NULL, ":");
         hold->next->address=strtok(NULL, ":");
         hold->next->LoginName=strtok(NULL, ":");
         hold->next->Password=strtok(NULL, "\n");
         hold->next->last=hold;
         }
       else {
         hold->next=hold;
         hold->ID=num;
           hold->name=strtok(NULL, ":");
            hold->address=strtok(NULL, ":");
         hold->LoginName=strtok(NULL, ":");
          hold->Password=strtok(NULL, "\n");
         hold->last=hold->next->last;
         hold->next->last=hold;
       }
      }
      if (num<hold->ID){
        while(num<hold->ID && hold->last!=NULL){
         hold=hold->last;
         }         
         if (hold->last==NULL){
         hold->last->ID=num;
         hold->last->name=strtok(NULL, ":");
         hold->last->address=strtok(NULL, ":");
         hold->last->LoginName=strtok(NULL, ":");
         hold->last->Password=strtok(NULL, "\n");
         hold->last->next=hold;
         }
       else {
         hold->last=hold;
         hold->ID=num;
           hold->name=strtok(NULL, ":");
            hold->address=strtok(NULL, ":");
         hold->LoginName=strtok(NULL, ":");
          hold->Password=strtok(NULL, "\n");
         hold->next=hold->last->next;
         hold->last->next=hold;
       }
      }
      }}}
    fgets(buffer, sizeof(buffer), f1);
    }
  }
if (strcmp(buffer, "ACCOUNTS") == 0){
  fgets(buffer, sizeof(buffer), f1);
  while (strcmp(buffer, "") != 0){
    num=atoi(strtok(buffer, ":"));
    num2=atoi(strtok(buffer, ":"));
    while (hold->ID<num2) hold=hold->next;
    while (hold->ID>num2) hold=hold->last;
    if (hold->ID=num2){
      temp=hold->list;
      if (temp==NULL){
      temp->num=num;
      temp->type=strtok(NULL, ":");
      temp->balance=atoi(strtok(NULL, ":"));
      temp->rate=atoi(strtok(NULL, "\n"));
      }
      else {
      if (temp->num>num){
        temp->next=temp;
        temp->num=num;
        temp->type=strtok(NULL, ":");
        temp->balance=atoi(strtok(NULL, ":"));
        temp->rate=atoi(strtok(NULL, "\n"));
        }
      else {
        while (temp->next->num>num) temp=temp->next;
        if (temp->next!=NULL)temp->next->next=temp->next;
        temp->next->num=num;
        temp->next->type=strtok(NULL, ":");
        temp->balance=atoi(strtok(NULL, ":"));
        temp->rate=atoi(strtok(NULL, "\n"));
      }
      }
    }
  fgets(buffer, sizeof(buffer), f1);
  }
}
fgets(buffer, sizeof(buffer), f1);
}
}

        

void listAllCustomers(){
struct Customer *hold;
hold = bank.list;
while(hold != NULL){
 printf("Customer ID: &d \n Name: %s \n", hold->ID, hold->name);
 printf("Address: %s \n Login Name: %s \n",hold->address,hold->LoginName);  
 printf("Password: %s", hold->Password);
 hold=hold->next;
 }
}

void listAllAccountsForCustomer(int cust){
struct Customer *hold;
hold = bank.list;
while (cust!=hold->ID){
  hold=hold->next;
  if (hold == NULL) {
    printf("Customer ID is not valid \n");
    return;}
  }
struct Account *temp;
temp = hold->list;
while (temp != NULL){
  printf("Account number: %d \n Type: %s \n", temp->num, temp->type);
  printf("Balance: %f \n Interest rate: %f \n", temp->balance,temp->rate);
  temp=temp->next;
  }
}
Comment
Watch Question

Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Author

Commented:
when I hit 4 it exits which is right, when I had 2 it prints the menu out which is fine since the function when you run 2 wouldn't do anything without loading a file first then prints the menu out twice though I don't know why twice, when I hit 3 it asks for the customer ID and then when I enter a number I get a segfault, and when I enter 1 it asks for the filename and then I get a segfault. Although I do have a file in the form this program would read, I get a segfault regardless of whether I enter the name of that or some non-existant file.

Commented:
In these statements:

void loadFile(char* filename){
f1 = fopen(filename, "r");
char *buffer;
struct Customer *head=bank.list;
struct Customer *hold = head;
struct Account *temp=head->list;


bank has been declared (Struct Bank bank), so it exists. Thus bank.list exists. It is a pointer to a customer, which is then assigned to head. The hold variable gets a copy of head. In the last line there is a reference to "head->list". However, bank.list (which head is a copy of) was never initialized to anything. It was never set to point to any valid place in memory. Thus, when you attempt to dereference it (looking for the list of the customers accounts), you will get a seg fault.

Author

Commented:
I think I understand now, but how do I go about fixing that?
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Author

Commented:
thanks, I missed that extra = there. So long as the program works I won't worry about where I declared things; it may not be "proper" necessarily, but it's my style so to speak for the time being. Still haven't figured out a way to get rid of the segmentation faults.
ok another error.

the basic problem is accessing a memory location without allocating it. In this case bank.list is a null pointer. and so head->list does not exist, becoz head is null.

void loadFile(char* filename){
f1 = fopen(filename, "r");
char *buffer;
struct Customer *head=bank.list;
struct Customer *hold = head;
struct Account *temp=head->list;
int num;
int num2;

So the statement:
struct Account *temp=head->list;

fails. From what i could see of the program the simple modification of using

struct Account *temp;

instead might work, becoz ur assigning 'temp' to 'list' later anyway. The segmentation fault is gone but i am not sure if it works still. Check with a proper input file.

Commented:
JeebusFnChrist,

Whevever you use a pointer, you have to give it a valid address before using it.
In your program, Bank is a structure and you have a variable bank of type Bank.
Now, bank contains a pointer list, which is of type Customer.
Since list is a pointer, you have to assign it proper address before using it.
So, whenever you create variables of type Bank, you have to assign memory (address) to the pointer list.
In the same way, the structure Customer contains many character pointers, which have to be assigned proper address.

At one place in the code, I see that you have used malloc. That means you know how to allocate memory. So, go ahead and allocate memory to each of the pointers you are using and your problems should disappear.

The reason for Segmentation Fault is that, address (memory) space for each process is divided into different segments. They are code segment, data segment, heap and stack. Out of this, you can write to all the segments except code segment. Your code will raise segmentation fault when it tries to write to a segment where you are not supposed to write to!
When you do malloc, program gets memory from heap and it's a valid memory to write and program will work properly.
Hope you understood why your program gave segmentation fault!?

-ssnkumar

Author

Commented:
I understand now why I got the error, and I changed the *temp not to be equal to head->list. When I did that, I was able to run the program and run the loadFile function, however when I tried to list customers it didn't output anything. Is this because of my failure to allocate memory, or do I just need to look over my loadFile function and make sure it is reading the file properly?

Commented:
Nine tenths of programming is debugging. Whenever you don't get the result you expect, your first job is to figure out where the programs behaviour diverges from what you expect. This can be done by printing things out as it progresses, or by using a debugger. The possible reasons for it not doing what you expect are legion.

So, follow what it is doing (step by step if necessary), and when you find out where it diverges, it is usually clear how to fix the problem. And, if it is not clear, you can always come back here and ask for help.
ok i think this could be another error.

What is probably happening is that the pointer to the stored data in loadfile is not being passed outside the function. I this case, you are assigning head = bank.list, so now head and bank.list point to the same location. now when you assign data to head->ID etc..  you are probably creating new memory for it and bank.list is no more pointing to this new memory though head is.

If this is the problem, it can be probably be solved be assigning
bank.list = head (or bank.list = hold)
at the end of loadfile() function.

try this out.
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Commented:
Did any of those comments help?

If so, it is now time to select an answer and grade it.

If not, perhaps a clarifying question would help.

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.