pledgehollywood
pledgehollywood

Reputation: 109

Odd Seg Fault error when scanning lines from a file in C

I've been working on a program where I need to use C to scan lines from a file and store them in a struct.

My .txt file is in the form:

NAME 0.2 0.3
NAME2 0.8 0.1

Or in general its a string followed by 2 doubles

My struct is:

struct device {
char* name;
double interruptProbability, interruptTime, startTime, endTime;
} myDevice;

Now, I'm able to scan the lines in fine, but when it comes time to put them into my struct, something gets messed up. Here's how I'm doing the scanning:

    char line[BUFSIZ];
    while(fgets (line, BUFSIZ, devicesFile) != NULL){
        struct device *d = &myDevice;
        if(!isspace(*line)){
            printf("String: %s \n", &line);
            d->name = "success"; // for testing purposes
            printf("device name before: %s \n", d[0]);
            sscanf(line, "%s %f %f",&d->name, &d->interruptProbability, &d->interruptTime);
            printf("device name after: %s \n", d[0]);
        }
    }

When I run this, it'll print off:

String: Disk 0.2 0.00005


device name before: success 

before giving me a seg fault.

I ran GDB to test whats going on with the scan, and for whatever reason it puts in d->name a huge hex number that has (Address out of bounds) next to it.

any ideas?

Upvotes: 0

Views: 173

Answers (4)

SecurityMatt
SecurityMatt

Reputation: 6743

You're sscanf-ing into a string literal. String literals are const char*s in C and C++, are are readonly, so sscanf will crash whilst trying to write to the string literal "success".

Upvotes: 0

paddy
paddy

Reputation: 63481

You can't scan a string into the pointer d->name.

Not even after you assign it a constant value:

d->name = "success"; // for testing purposes

You need to allocate memory for it, or make it an array. You should be very careful using sscanf to read strings. It might be better to use strtok or just strchr to find the first space and then copy the bytes out with strdup.

char *next = strchr(line, ' ');
if( next != NULL ) {
    *next++ = 0;             // Terminate string and move to next token.
    d->name = strdup(line);  // Make a copy of tokenised string

    // Read the floats - note you should check that the result is equal to 2.
    count = sscanf(next, "%f %f", d->interruptProbability, d->interruptTime);
}

Upvotes: 0

addiedx44
addiedx44

Reputation: 2743

You are not allocating space for each of your char *name. You need to add d->name = (char *)malloc(<length of the token>*sizeof(char)+1) before your sscanf call.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409442

It's because you're overwriting a literal string in the sscanf call. d->name points to a literal string, and those are read-only and of a fixed length (so if the string you try to get is longer than 7 character you also try to write beyond the end).

You need to either use an array for d->name or allocate memory on the heap for it.

Upvotes: 1

Related Questions