user3075178
user3075178

Reputation: 5

Segmentation Fault in C. Works in main but not my function

I am trying to create a program that will check a name the user enters to a file and see how many occurences there are of it within the file. However in my getrawdata func I keep getting a segmentation fault.

Here is the code:

struct NameRecord{ // Holds all the name information
    int year;
    char name [31];
    int frequency;
};


void allCaps(char s[]){ //Capitalizes all of the characters of s
    int i=0;
    while (s[i])
        {
            s[i] = toupper(s[i]);
            i++;
        }
    printf("The name entered is now in all caps! %s", s);
}

int getRawData1(FILE* male, struct NameRecord records[], int currSize){
    int readResult;
    printf("The current size is %d", currSize);
    readResult=fscanf(&*male, "%d", &records[currSize].year);
}
//Main
int main (){
    char name [31];
    FILE *male;
    FILE *female;
    int size = 0;
    //Opening files
    male = fopen("malebabynames.csv", "r"); //Dont leave in home directory 
    female = fopen("femalebabynames.csv", "r");
    struct NameRecord records[160000];

    if ( male==NULL){
        printf ("Error: the data file does not exist");
    }
    if ( female==NULL){
        printf ("Error: the data file does not exist");
    }

    size = getRawData1(male, records, size);
    //Output   
    printf("Please enter a name: ");
    scanf("%s", name);
    allCaps(name);
}

Revised code — still crashing

Original version at Codepad; this version SSCCE'd.

#include <stdio.h>

struct NameRecord
{
    int year;
    char name[31];
    int frequency;
};
struct NameRecord records[160000];

void allCaps(char s[])
{
    int i = 0;
    while (s[i])
    {
        s[i] = toupper(s[i]);
        i++;
    }
    printf("The name entered is now in all caps! %s", s);
}

int getRawData1(FILE *male, struct NameRecord records[], int currSize)
{
    int readResult;
    printf("The current size is %d", currSize);
    readResult = fscanf(male, "%d,%[^,],%d\n", &records[currSize].year,
                        records[currSize].name, records[currSize].frequency);

    while (readResult == 3)
    {
        currSize++;
        readResult = fscanf(male, "%d,%[^,],%d\n", &records[currSize].year,
                            records[currSize].name, &records[currSize].frequency);
    }
    printf("The size of the array is %d", currSize);
    return currSize;
}

int main()
{
    char name[31];
    FILE *male;
    FILE *female;
    int size = 0;

    male = fopen("malebabynames.csv", "r");
    female = fopen("femalebabynames.csv", "r");
    int i = 0;
    int readResult;
    if (male == NULL)
    {
        printf("Error: the data file does not exist");
    }
    if (female == NULL)
    {
        printf("Error: the data file does not exist");
    }
    getRawData1(male, records, size);

    printf("Welcome to the Name Popularity Checker \n====================================== \n");
    printf("Please enter a name: ");
    scanf("%s", name);
    allCaps(name);
}

Upvotes: 0

Views: 120

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 755094

Pay attention to compiler warnings. If you aren't getting compiler warnings, turn them on; if you still aren't getting compiler warnings, get a better compiler.

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition x.c -o x
x.c: In function ‘getRawData1’:
x.c:30:25: warning: format ‘%d’ expects argument of type ‘int *’, but argument 5 has type ‘int’ [-Wformat=]
                         records[currSize].name, records[currSize].frequency);
                         ^
x.c:30:25: warning: format ‘%d’ expects argument of type ‘int *’, but argument 5 has type ‘int’ [-Wformat=]
$

You are missing an &.

                         records[currSize].name, &records[currSize].frequency);

(I'd already added #include <ctype.h> and put static in front of the functions to quell other warnings from the compiler.)


You should also redesign the interface to getRawData1():

int getRawData1(FILE *fp, struct NameRecord records[], int maxSize)
{
    int readResult;
    printf("The maximum size is %d", maxSize);
    int currSize = 0;

    while (currSize < maxSize &&
           (readResult = fscanf(fp, "%d,%[^,],%d\n", &records[currSize].year,
                                records[currSize].name, &records[currSize].frequency)) == 3)
        currSize++;

    printf("The amount of data in the array is %d", currSize);
    return currSize;
}

Called:

num_male_names = getRawData1(male, records, 160000);

This prevents buffer overflow if there are more than 160,000 records in the file.

Upvotes: 1

aardvarkk
aardvarkk

Reputation: 15996

This actually crashes in VS2012 for me on startup because of this line:

struct NameRecord records[160000];

I think you may be exceeding your available stack space. At least it was for me! Does that number need to be so high? Can you dynamically allocate based on what you read in from the file?

Taking Barmar's suggestion below, you can do this to fix it (if you really need a static allocation of 160k records):

struct NameRecord{ // Holds all the name information
  int year;
  char name [31];
  int frequency;
};

NameRecord records[160000];

In other words, make it a global variable instead of a variable on the stack.

UPDATE: Also, using Jonathan Leffler's advice, you could make sure you're opening the files correctly. You're currently just printing a message if the files don't open correctly, but you should not continue execution if that's the case.

if (male == NULL)
{
    printf("Error: the data file does not exist");
    return EXIT_FAILURE;
}
if (female == NULL)
{
    printf("Error: the data file does not exist");
    return EXIT_FAILURE;
}

Upvotes: 1

Related Questions