5
votes

I'm currently writing a program that will read the file /proc/stat and parse each line, to be stored as tokens and then eventually processed and represented in an output table. I'm at the stage where I have been able to get the program to parse the program but when it comes to storing the tokens in various array values, I am getting the error: Segmentation fault (core dumped). I'm not sure what is causing this as I have allocated memory already. I am also pretty much a beginner with C.

//standard input/output file to help with io operations
#include<stdio.h>
//standard library files to help with exit and other standard functions
#include<stdlib.h>
//header file for usleep function
#include <unistd.h>
#include <string.h> //header file for strtok function

int main()
{
//FILE pointer will need to be declared initially, in this example the name is fp
FILE *fp;
//A character pointer that will store each line within the file; you will need to parse this line to extract useful information
char *str = NULL;
//size_t defined within C is a unsigned integer; you may need this for getline(..) function from stdio.h to allocate buffer dynamically
size_t len = 0;
//ssize_t is used to represent the sizes of blocks that can be read or written in a single operation through getline(..). It is similar to size_t, but must be a signed type.
ssize_t read;
float cpu_line1[4];
float cpu_line2[4];
float cpu_line3[4];
float cpu_line4[4];
float cpu_line5[4];
float page[2];
float swap[2];
float intr;
float ctxt;
float btime;


//a variable declared to keep track of the number of times we read back the file
unsigned int sample_count = 0;

//opening the file in read mode; this file must be closed after you are done through fclose(..); note that explicit location of the file to ensure file can be found
fp = fopen("/proc/stat", "r");

//checking if the file opening was successful; if not we do not want to proceed further and exit with failure code right away
if(fp == NULL)
{
    exit(EXIT_FAILURE);
}
int i = 0;
char **string = NULL; //declaration of string
string = (char**)malloc(10*sizeof(char*)); //assign space for 10 pointers to array
for (i=0; i<10; i++) //allocate 50 bytes to each string in the array
{
    string[i] = (char*)malloc(50*sizeof(char));
}
char *s = NULL;

//a loop that will read one line in the file at a time; str will read the line; len will store the length of the file
while(1)
{
    printf("\e[1;1H\e[2J"); //this line will make sure you have cleared the previous screen using C's powerful format specifiers
    printf("----------------------------------------------------------------\n");//used for presentation
    printf("Sample: %u\n", sample_count); //showing the sample count
    int i = 0; //counter

    while ((read = getline(&str, &len, fp)) != -1)
    {
       // printf("Retrieved line: \n%sof length: %zu, allocated buffer: %u :\n", str, read, (unsigned int) len);

        s = strtok(str, " ");
        printf("Test program: %s\n", s);
    }

    if (i=0)
    {
        sprintf(string[0], s);
        cpu_line1[0] = atoi(strtok(NULL, " "));
        cpu_line1[1] = atoi(strtok(NULL, " "));
        cpu_line1[2] = atoi(strtok(NULL, " "));
        cpu_line1[3] = atoi(strtok(NULL, " "));
    }

    if (i=1)
    {
        sprintf(string[1], s);
        cpu_line2[0] = atoi(strtok(NULL, " "));
        cpu_line2[1] = atoi(strtok(NULL, " "));
        cpu_line2[2] = atoi(strtok(NULL, " "));
        cpu_line2[3] = atoi(strtok(NULL, " "));
    }

    if (i=2)
    {
        sprintf(string[2], s);
        cpu_line3[0] = atoi(strtok(NULL, " "));
        cpu_line3[1] = atoi(strtok(NULL, " "));
        cpu_line3[2] = atoi(strtok(NULL, " "));
        cpu_line3[3] = atoi(strtok(NULL, " "));
    }

    if (i=3)
    {
        sprintf(string[3], s);
        cpu_line4[0] = atoi(strtok(NULL, " "));
        cpu_line4[1] = atoi(strtok(NULL, " "));
        cpu_line4[2] = atoi(strtok(NULL, " "));
        cpu_line4[3] = atoi(strtok(NULL, " "));
    }

    if (i=4)
    {
        sprintf(string[4], s);
        cpu_line5[0] = atoi(strtok(NULL, " "));
        cpu_line5[1] = atoi(strtok(NULL, " "));
        cpu_line5[2] = atoi(strtok(NULL, " "));
        cpu_line5[3] = atoi(strtok(NULL, " "));
    }

    if(i=5)
    {
        sprintf(string[5], s);
        page[0] = atoi(strtok(NULL, " "));
        page[1] = atoi(strtok(NULL, " "));
    }

    if(i=6)
    {
        sprintf(string[6], s);
        swap[0] = atoi(strtok(NULL, " "));
        swap[1] = atoi(strtok(NULL, " "));
    }

    if(i=7)
    {
        sprintf(string[7], s);
        intr = atoi(strtok(NULL, " "));
    }

    if(i=8)
    {
        sprintf(string[8], s);
        ctxt = atoi(strtok(NULL, " "));
    }

    if(i=9)
    {
        sprintf(string[9], s);
        btime = atoi(strtok(NULL, " "));
    }

    printf("----------------------------------------------------------------\n"); //used for presentation
    usleep(500000);//this will ensure time delay
    rewind(fp);//rewind the file pointer to start reading from the beginning
    sample_count++;//update the sample count
}
//Frees pointers to make program memory efficient
free(str);
for (i=0; i <10; i++)
{
    free(string[i]);
}
//once you are done, you should also close all file pointers to make your program memory efficient
fclose(fp);


return 0;

}

EDIT Here is a copy of what the program looks like when run in Cygwin


Sample: 0

Test program: cpu

Test program: cpu0

Test program: cpu1

Test program: cpu2

Test program: cpu3

Test program: page

Test program: swap

Test program: intr

Test program: ctxt

Test program: btime

Segmentation fault (core dumped)

3
What are you trying to do with the sprintf statements? If you are trying to copy the content of s to string[i], you should use the strcpy function. In sprintf the second argument is a format string, and depending on what's in there, nasty things could happen.Hellmar Becker
Enable compiler warnings (= !).Karoly Horvath
That's a lot of code, where does the crash happen? In which cases? For what input? What are the values of the involved variables when the crash happens? Do you get compiler warnings? If you enable more warnings, what then?Some programmer dude
@HellmarBecker Whats the problem with sprintf ?ameyCU
@JoachimPileborg basically the program successfully prints the test statements, there's no compiler warnings. After this the program crashes.J Hall

3 Answers

3
votes

Among other things, your conditions are incorrect:

if (i = 1) {
    // do something.
}

This assigns the value 1 to i instead of comparing to 1. Try condition as i == 1.

3
votes

Not sure why Segmentation fault but i can tell you that if you write

if (i=0) //it means assign the value 0 to i and if the value would be different from zero, follow the "then" branch
if (i==0) //is compare i to 0 and if true follow the "then" branch

So all the if there are wrong.

Hope this helps :)

1
votes

As mentioned in the other anwers you should replace if(i=0) with if(i==0).

You get a segmentation fault because strtok() returns NULL and thus atoi() gets NULL as parameter:

    cpu_line1[0] = atoi(strtok(NULL, " "));
    cpu_line1[1] = atoi(strtok(NULL, " "));
    cpu_line1[2] = atoi(strtok(NULL, " "));
    cpu_line1[3] = atoi(strtok(NULL, " "));

This code works ok as long as there are enough tokens to parse. But as it seems you're trying to get the next token too often.

You should check if the return value of strtok() is NULL before giving it to atoi(). I suggest to use loops to simplify your code and apply the check for NULL to every use of atoi().

Here is a simple example for the check:

char* token = strtok(NULL, " ");
if(token != NULL)
    cpu_line1[0] = atoi(token);

This should solve your segmentation fault problem if you add the check to every strtok() call.