C程序指针崩溃系统调用

时间:2013-01-31 16:50:48

标签: c pointers system

// Struct for Country Data
typedef struct
{
    char name[50];          // Country name
    char code[3];           // Country code
    int population;         // Country Population
    double lifeExp;         // Country Life expectancy  

}   CountryData;

// Struct for Dir File
typedef struct
{
    char code[3];
    int offSet;

}   DirData;

// Function Declarations
void fillCountryStructs(CountryData ** dataPtr, int nLines, int fd);
void fillDirectoryStructs(CountryData **dataPtr, DirData **director, int nLines,int fd2);
void sortStructs(DirData **director, int nLines);
int verifyString(char *s1, char *s2);

// Main Function
// - This function starts the program, get the number of lines as a 
//   parameter, fills the structs and writes the data to the Country
//   File and the Directory file.
int main(int argc, char *argv[])        // Always remember to pass an argument while executing
{
    // Some variables
    int nLines;             // The number of lines
    char *pEnd;             // For String functions
    FILE *Fin,*Fout;        // File pointers
    int fd; 
    int fd2;
    nLines = strtod(argv[1], &pEnd); 
    CountryData **countryDataPtr;   // Array of structs
    CountryData **tempStruct;
    DirData **director;

    // Allocate memory for the struct pointers
    countryDataPtr = calloc(nLines, sizeof(CountryData*));
    director = calloc(nLines, sizeof(DirData*));

    // File Stream for "AllCountries.dat"
    if((fd = open("AllCountries.dat", O_RDWR)) ==-1)
        err_sys("File not found...\n");
    // File Stream for "RandomStruct.bin"
    if ((fd2 = open("RandomStruct.bin", O_RDWR)) == -1) 
        err_sys("Failed to open binary\n");

    // Filling the Country stucts
    fillCountryStructs(countryDataPtr, nLines, fd);
    close (fd);
    //fclose(Fin);                                      // Closing the file "AllCountries.dat"
    // Writing Binary File
    write(fd2, (countryDataPtr[0]->name[0]), sizeof(CountryData));
    close (fd2);
    //fclose(Fout);
    printf("RandomStruct.bin written Sucessfully\n");

    // Filling the Directory File
    // File Stream for "RandomStructDir.dir"
    if ((fd2 = open("RandomStructDir.dir",O_RDWR|O_TRUNC)) != -1) 
        err_sys("Failed to open binary\n");

    fillDirectoryStructs(countryDataPtr, director, nLines, fd2);
    sortStructs(director, nLines);                                  // Sorting the structs

    // Write the number of lines in the FIRST LINE
    // of the Directory File
    write(fd2, nLines, sizeof(nLines));
    // Writing Directory File after the number of lines was written
    write(fd2,(director[0]->code[0]), sizeof(DirData));
    close (fd2);
    //fclose(Fout);
    printf("RandomStructDir.dir written Sucessfully\n\n");

    exit(0);
}

// Filling the Country structs
// - This function extracts the data from the file using strtok 
//   and fills all the structs with their corresponding values.
void fillCountryStructs(CountryData **dataPtr, int nLines, int fd)
{
    int curLine = 0;        // Current line
    int index = 0;          // The index
    char buf[BUFSIZE];      // The Buffer with the size of BUFSIZE
    char *tok;              // Token
    char *pEnd;             // For the String functions
        char ch = 'a'; // The temp character
    int temPop;
    double temLifeExp;  
    int num=0;

    for(curLine = 0; curLine < nLines; curLine++)
    {
       // Reading each line
    dataPtr[curLine] = (CountryData *)calloc(1, sizeof(CountryData));
    index = 0;
    do
    {
    read(fd, &ch, 1);
    buf[index++] = ch;
    }
    while(ch != '\n');

        // Strtoking...
        tok = strtok(buf, ",\n");

        index = 1;
        while(tok != NULL)
        {
            tok = strtok(NULL, ",\n");

            // Get the Country Code
            if(index == 1)
            {
                strcpy(dataPtr[curLine]->code, tok);        // Copying code to the struct
            }
            // Get the Country Name
            if(index == 2)
            {
                strcpy(dataPtr[curLine]->name, tok);        // Copying name to the struct
            }
            // Get the Country Population
            if(index == 7)
            {
                temPop = (int)strtol(tok, &pEnd, 10);
                dataPtr[curLine]->population = temPop;      // Copying population to the struct
            }
            // Get the Country Life expectancy
            if(index == 8)
            {
             num=countchar(tok);
          printf ("The number of characters entered is %d\n", num);
          printf ("The character entered is %s\n",tok);
                temLifeExp = strtod(tok, &pEnd);
                dataPtr[curLine]->lifeExp = temLifeExp;     // Copying life expectancy to the struct
            }
            index++;
        }
    }
}


int countchar (char list[])
{
        int i, count = 0;
        for (i = 0; list[i] != '\0'; i++)
        count++;
        return (count);
}



// Filling the Directory Structs
// - This function fills the directory with the offset
void fillDirectoryStructs(CountryData **dataPtr, DirData **director, int nLines, int fd2)
{

    int i = 0;
    for(i = 0; i < nLines; i++)
    {
        strcpy(director[i]->code, dataPtr[i]->code);      //It crashes in this Line
        director[i]->offSet = sizeof(CountryData) * (i);        
    }   
}

// Sorting the Dir Structs
// - This function sorts the Directory Structs.
void sortStructs(DirData **director, int nLines)
{

    int maxNumber;
    int i;
    DirData **temp;
    temp = calloc(1, sizeof(DirData));

    // Sorting the array of pointers!
    for(maxNumber = nLines - 1; maxNumber > 0; maxNumber--)
    {
        for(i = 0; i < maxNumber; i++)
        {
            if((verifyString(director[i]->code, director[i+1]->code)) == 1)
            {
                temp[0] = director[i];
                director[i] = director[i+1];
                director[i+1] = temp[0];
            }           
        }           
    }
}

// Veryfying the strings
// - This function compares two strings and return a specific value
//   accordingly.
int verifyString(char *s1, char *s2)
{
    int i;
    if(strcmp(s1,s2) == 0)
        return(0);          // They are equal

    for(i = 0; s1[i] != 0; i++)
    {
        if(s1[i] > s2[i])
            return(1);              // s1 is greater
        else if(s1[i] < s2[i])
            return(2);              // s2 is greater
    }

    return (2); // s2 is greater
}

所以我得到分段错误,我不明白为什么?也许是关于指针的东西。我指定了第一行方法崩溃的地方(void fillDirectoryStructs)。

当我编译时,我得到:

Countries.c: In function 'main':
Countries.c:68: warning: passing argument 2 of 'write' makes pointer from integer without a cast
Countries.c:84: warning: passing argument 2 of 'write' makes pointer from integer without a cast
Countries.c:86: warning: passing argument 2 of 'write' makes pointer from integer without a cast
Countries.c:232:2: warning: no newline at end of file

我对指针知之甚少,但我必须使用系统调用,所以我不能使用任何FILE *函数(fwrite()等)这就是为什么我是使用普通write()read()

当我运行它时,当它到达我刚刚指定的那个点时,我会遇到分段错误。

出于测试目的,我正在尝试打印此

printf("test: %s\n", countryDataPtr[0]->code[0]);

而不是写作,它崩溃了,为什么?我究竟做错了什么?不应该在我的结构中得到第一个国家的代码?感谢

2 个答案:

答案 0 :(得分:8)

嗯,你需要倾听你的编译器并认真对待它的警告。

此:

write(fd2, nLines, sizeof(nLines));

错了,并会解释警告。变量nLines的类型为int,但如果查看[{1}}的[文档],您会发现第二个参数的类型为write()

因此它会将您的整数值解释为指针,并开始读取您无权阅读的内存。

你需要:

void *

请注意write(fd2, &nLines, sizeof nLines); 不是函数,当参数是类型名称时它只需要括号(因为它需要对所讨论的类型使用强制转换表达式,并且强制转换为附加的类型名称)括号)。

此外,您需要为I / O可能失败的现实做好准备。 sizeof函数有一个您应该检查的返回值。

答案 1 :(得分:1)

您的代码还有许多其他问题,除了严重的解除指出。

此:

CountryData **countryDataPtr;   // Array of structs

Array of structs。分配后,它可能是指向结构的指针数组。

此:

write(fd2, (countryDataPtr[0]->name[0]), sizeof(CountryData));

写一个CountryData实例(更不用说它们的整个数组)了。它采用第一个元素名称的第一个字符的整数值,并将其视为指针,就像使用nLines一样。

如果你想写第一个元素,它将如下所示:

write(fd2, countryDataPtr[0], sizeof(CountryData));

如果你想编写所有元素,你需要一个循环,或者你可以一次编写一个连续的结构数组。