[英]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.