簡體   English   中英

將行讀入動態分配的char指針數組時出現段錯誤

[英]Seg fault when reading a line into dynamically allocated char pointer array

在C語言中,我試圖實現一個使用getline()從文件讀取所有行的函數。 它的實現與getline()類似,特別是以下事實:如果沒有足夠的內存分配來存儲指向行的下一個指針,它將使用realloc()來調整char**大小。 不幸的是,在字符串復制過程中出現段錯誤。

經過一番摸索之后,我發現該段錯誤發生在第二次迭代中,同時嘗試將第二行存儲在char指針數組中。

ssize_t fgetlines(char*** linesptr, size_t* n, FILE* fp)
{
    char* line = NULL;
    size_t sz_line = 0;
    size_t cur_len = 0;
    size_t needed;

    if (linesptr == NULL || n == NULL) {
        errno = EINVAL;
        return -1;
    }

    if (*linesptr == NULL) {
        if (*n == 0)
            *n = sizeof(**linesptr) * 30; /* assume 30 lines */
        *linesptr = malloc(*n);
        if (*linesptr == NULL) {
            *n = 0;
            return -1;
        }
    }

    while (getline(&line, &sz_line, fp) > 0) {
        needed = (cur_len + 1) * sizeof(**linesptr);
        while (needed > *n) {
            char** new_linesptr;
            *n *= 2;
            new_linesptr = realloc(*linesptr, *n);
            if (new_linesptr == NULL) {
                *n /= 2;
                free(line);
                return -1;
            }
            *linesptr = new_linesptr;
        }
        *linesptr[cur_len] = strdup(line);
        printf("%s", *linesptr[cur_len]);
        if (*linesptr[cur_len] == NULL) {
            free(line);
            free(*linesptr);
            return -1;
        }
        ++cur_len;
    }

    free(line);
    return cur_len;
}

我這樣調用該函數:

    char **settings = NULL;
    size_t sz_settings = sizeof(*settings) * 6;
    int count = fgetlines(&settings, &sz_settings, f_cfg);

由於該功能無法成功完成,因此我沒有任何輸出。 但是在strdup()之后打印回字符串之后,我設法在段錯誤之前獲得了f_cfg一行"Hello World"

正如chux所指出的,此處的預期優先級是不正確的。 *linesptr[cur_len]引用必須更改為(*linesptr[cur_len]) 代碼孔*n == 0 and *n *= 2也已修復。

應該改變

*linesptr[cur_len]  =>  (*linesptr)[cur_len]

修改后的功能如下:

ssize_t fgetlines(char *** linesptr, size_t *n, FILE *fp)
{
    char *line = NULL;
    size_t sz_line = 0;
    size_t cur_len = 0;
    size_t needed;

    if (linesptr == NULL || n == NULL) {
        errno = EINVAL;
        return -1;
    }

    if (*linesptr == NULL) {
        if (*n == 0)
            *n = sizeof(**linesptr) * 30; /* assume 30 lines */
        *linesptr = malloc(*n);
        if (*linesptr == NULL) {
            *n = 0;
            return -1;
        }
    }

    while (getline(&line, &sz_line, fp) > 0) {
        needed = (cur_len + 1) * sizeof(**linesptr);
        while (needed > *n) {
            char **new_linesptr;
            *n *= 2;
            new_linesptr = realloc(*linesptr, *n);
            if (new_linesptr == NULL) {
                *n /= 2;
                free(line);
                return -1; // Possible memory leak
            }
            *linesptr = new_linesptr;
        }
        (*linesptr)[cur_len] = strdup(line);
        printf("%s", (*linesptr)[cur_len]);
        if ((*linesptr)[cur_len] == NULL) {
            free(line);
            free(*linesptr);
            return -1;  // Possible memory leak
        }
        ++cur_len;
    }

    free(line);
    return cur_len;
}

另外,當您的內存分配失敗時,“ strdup”的內存不是空閑的,這將導致內存泄漏。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM