简体   繁体   English

C:使用 strcpy 将字符串分配给结构数组导致的段错误

[英]C: Segfault caused by assigning string to struct array using strcpy

I am reading in a text file containing 10 rows and 3 columns.我正在阅读一个包含 10 行和 3 列的文本文件。 Each element needs to be put into an array for further manipulation.每个元素都需要放入一个数组中以进行进一步操作。 The fileToArray method will single out each string and i can successfully print each string individually however I cannot seem to assign the strings to each index correctly. fileToArray 方法将挑选出每个字符串,我可以成功地单独打印每个字符串,但是我似乎无法正确地将字符串分配给每个索引。

My understanding is that i have a pointer to 10 dataArrays and in my switch statement what essentially happens is dataArray[0].pName = P1... dataArray[1].pName = P2... etc... and similarly for the other variables in the struct.我的理解是我有一个指向 10 个 dataArrays 的指针,在我的 switch 语句中,本质上发生的是 dataArray[0].pName = P1... dataArray[1].pName = P2... etc... 和类似的结构中的其他变量。

The text file has a max of 10 rows hence why 10 arrays are initialized.文本文件最多有 10 行,因此为什么要初始化 10 个 arrays。

Is my understanding flawed or is there some blatant errors in my code?我的理解有缺陷还是我的代码中有一些明显的错误?

struct Processes
{
    char *pName;
    char *arvTime;
    char *srvTime;
};
void fileToArray(FILE *fp, struct Processes dataArray[])
{
    // temp[14] because 14 is the max size a line can be
    char temp[14];
    char delim[] = " \n";
    int count = 0;
    int a, b, c = 0;

    while(fgets(temp, 14, fp) != NULL)
    {
        char *ptr = strtok(temp, delim);

        while(ptr != NULL)
        {
            // printf("'%s'\n", ptr);
            // ^^^^ This line will successfully print out each string

            switch(count)
            {
            case 0:
                dataArray[a].pName = malloc(strlen(ptr + 1));
                strcpy(dataArray[a].pName, ptr);
                a++;
                count++;
                free(dataArray[a].pName);
                break;

            case 1:
                dataArray[b].arvTime = malloc(strlen(ptr + 1));
                strcpy(dataArray[b].arvTime, ptr);
                b++;
                count++;
                free(dataArray[b].arvTime);
                break;

            case 2:
                dataArray[c].srvTime = malloc(strlen(ptr + 1));
                strcpy(dataArray[c].srvTime, ptr);
                c++;
                count = 0;
                free(dataArray[c].srvTime);
                break;
            }


            ptr = strtok(NULL, delim);

        }
    }
}
int main(int argc, void *argv[])
{
    struct Processes dataArray[10];

    if(argc == 1)
    {
        FILE *fp;

        fp = fopen("process-data.txt", "r");

        fileToArray(fp, dataArray);

        fclose(fp);
    }
    return 0;
}
// Sample text file being read //
P1 1 5
P2 2 2
P3 11 5
P4 17 9
P5 3 1
P6 10 10
P7 4 3
P8 4 1
P9 7 8
P10 5 4

Running this code results in a segfault and i am unsure as to why.运行此代码会导致段错误,我不确定原因。 Looking at other similar posts the solution seems to be not using malloc() which makes me think i have implemented the function incorrectly.查看其他类似的帖子,该解决方案似乎没有使用 malloc() 这让我认为我错误地实现了 function。

This bit of code is doing the exact opposite of what you think这段代码的作用与您的想法完全相反

malloc(strlen(ptr + 1))

Instead of allocating enough space for the string plus 1 extra for the NUL at the end, it is allocating one less than the length of the string.它不是为字符串分配足够的空间,最后为 NUL 分配 1 个额外的空间,而是分配比字符串长度少 1 个的空间。 You want to move the + 1 to the outside of call to strlen like this您想像这样将+ 1移到strlen的调用之外

malloc(strlen(ptr)+1)

Also you should initialise the values of a and b to 0 or better yet, combine a , b and c into one variable and only increment it when you've read in the 3rd piece of information.此外,您应该将ab的值初始化为 0 或更好,将abc成一个变量,并且仅在您读入第三条信息时才增加它。

For starters you should to pass to the function the number of elements in the array.对于初学者,您应该将数组中的元素数传递给 function。 So the function declaration should look like所以 function 声明应该看起来像

void fileToArray( struct Processes dataArray[], size_t n, FILE *fp );

And it is better when the function returns the number of the filled elements of the array.当 function 返回数组填充元素的数量时会更好。

size_t fileToArray( struct Processes dataArray[], size_t n, FILE *fp );

and the function can be called at least like并且 function 至少可以称为

size_t n = fileToArray( dataArray, 10, fp );

In this declaration在这份声明中

int a, b, c = 0;

only the variable c is initialized.只有变量c被初始化。 All other variables, a, and b, are not initialized.所有其他变量 a 和 b 均未初始化。 So for example this statement所以例如这个语句

dataArray[a].pName = malloc(strlen(ptr + 1));

results in undefined behavior.导致未定义的行为。

This expression这个表达

malloc(strlen(ptr + 1))

is invalid.是无效的。 It is equivalent to它相当于

malloc(strlen( &ptr[1] ))

And there is no any sense to free memory at once after its allocation.并且在 memory 分配后立即释放它是没有任何意义的。

free(dataArray[a].pName);

The function could be defined the following way function 可以通过以下方式定义

size_t fileToArray( struct Processes dataArray[], size_t n, FILE *fp )
{
    // temp[14] because 14 is the max size a line can be
    char temp[14];
    char delim[] = " \n";

    size_t i = 0;

    for( ; i < n && fgets( temp, sizeof( temp ), fp) != NULL; i++ )
    {
        dataArray[i].pName   = NULL;
        dataArray[i].arvTime = NULL;
        dataArray[i].srvTime = NULL;

        char *ptr = strtok( temp, delim );

        for( size_t j = 0; j < 3 && ptr != NULL; j++ )
        {
            switch ( j )
            {
            case 0:
                dataArray[i].pName = malloc( strlen( ptr ) + 1 );
                strcpy( dataArray[i].pName, ptr );
                break;

            case 1:
                dataArray[i].arvTime = malloc( strlen( ptr ) + 1 );
                strcpy( dataArray[i].arvTime, ptr );
                break;

            case 2:
                dataArray[i].srvTime = malloc( strlen( ptr ) + 1 );
                strcpy( dataArray[i].srvTime, ptr );
                break;
            }

            ptr = strtok( NULL, delim );
        }
    }

    return i;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM