簡體   English   中英

重新分配,char **,segfault

[英]Realloc, char**, segfault

有一個功能。 它是add_lexem,並在指定數組and的末尾添加一個元素(char *)。 如果沒有剩余的內存,它將分配一些額外的內存(100 * sizeof(char *))。 該功能導致段錯誤,這就是問題所在。

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void add_lexem(char **lexems, int *lexemsc, int *lexem_n, const char *lexem)
{
    if (*lexem_n >= *lexemsc) {
        lexems = realloc(lexems, sizeof(char *) * (*lexemsc + 100));
        *lexemsc += 100;
    }

    char *for_adding = malloc(sizeof(char) * strlen(lexem));
    strcpy(for_adding, lexem);
    lexems[*lexem_n] = for_adding;
    (*lexem_n)++;
}

int main(void)
{
    char **D = malloc(sizeof(char *) * 2);
    int lexemsc = 2;
    int lexem_n = 0;

    add_lexem(D, &lexemsc, &lexem_n, "MEOW");
    printf("%s\n", D[0]);

    add_lexem(D, &lexemsc, &lexem_n, "BARK");
    printf("%s\n", D[1]);

    // in this place lexem_n becomes equal lexemsc
    add_lexem(D, &lexemsc, &lexem_n, "KWARK"); 
    printf("%s\n", D[2]);

    return 0;
}

輸出必須是

MEOW
BARK
KWARK

但它是

MEOW
BARK
Segmentation fault (core dumped)

您正在按值傳遞lexeme參數,而該參數應按地址傳遞:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

// removed unused void ccat(char *str, char c)

void add_lexem(char ***lexems, int *lexemsc, int *lexem_n, const char *lexem)
{
    if (*lexem_n >= *lexemsc) {
        *lexems = realloc(*lexems, sizeof(char *) * (*lexemsc + 100));
        *lexemsc += 100;
    }

    char *for_adding = malloc(sizeof(char) * strlen(lexem)+1);
    strcpy(for_adding, lexem);
    (*lexems)[*lexem_n] = for_adding;
    (*lexem_n)++;
}

int main(void)
{
    char **D = malloc(sizeof(char *) * 2);
    int lexemsc = 2;
    int lexem_n = 0;

    add_lexem(&D, &lexemsc, &lexem_n, "MEOW");
    printf("%s\n", D[0]);

    add_lexem(&D, &lexemsc, &lexem_n, "BARK");
    printf("%s\n", D[1]);

    // in this place lexem_n becomes equal lexemsc
    add_lexem(&D, &lexemsc, &lexem_n, "KWARK");
    printf("%s\n", D[2]);

    return 0;
}

輸出量

MEOW
BARK
KWARK

注意:三重間接尋址(即3-start-programming)並不是一件容易的事,盡管它實際上符合您在此處試圖做的事情。 請仔細閱讀以上代碼,並確保您了解其工作方式。

編輯 :為添加的字符串添加了終止符空間。 (不知道為什么我會錯過它,因為這是其他所有人都在初審中發現的東西,du)。

注意:請參閱@wildplasser對這個問題的回答 老實說,這是最好的方法,因為它加強了字符串指針數組與“相同大小”之間的關系。 如果可以重新編寫代碼以使用該模型,則應該這樣做,並在這樣做時選擇該答案作為“正確”的解決方案。

主要問題是您要按值將D傳遞給函數:賦值

lexems = realloc(...);

D沒有影響。 realloc執行重新分配的情況下, D成為懸空指針,因此對其取消引用成為未定義的行為。

您需要以與傳遞lexemsc&lexem_n相同的方式通過指針傳遞D ,以便realloc的效果在main函數中也可見。

另外,您的add_lexem沒有為要復制的字符串分配足夠的內存: strlen不計算空終止符,因此這兩行

char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);

在分配的空間后寫一個字節'\\0'

避免三星級編程的替代方法:將所需的所有內容放入結構中:

struct wordbag {
        size_t size;
        size_t used;
        char **bag;
        };

void add_lexem(struct wordbag *wb, const char *lexem)
{
    if (wb->used >= wb->size) {
        wb->bag = realloc(wb->bag, (wb->size+100) * sizeof *wb->bag );
        wb->size += 100;
    }

    wb->bag[wb->used++] = strdup(lexem);
}

問題可能來自:

 char *for_adding = malloc(sizeof(char) * strlen(lexem));
  strcpy(for_adding, lexem);

嘗試char *for_adding = malloc(sizeof(char) * (strlen(lexem)+1)); 為' \\0字符留一些空間。

編輯:和@WhozCraig似乎是正確的!

再見

暫無
暫無

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

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