有一个功能。它是add_lexem并在指定数组的末尾添加一个元素(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)
答案 0 :(得分:3)
您的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开始编程)不是轻易进入的,尽管它实际上符合您在此处尝试做的事情。仔细阅读上面的代码并确保确定,了解它是如何工作的。
编辑:为添加的字符串添加了终结符空间。 (不知道为什么我错过了它,因为这是其他所有人似乎都在第一次审查时所发现的,呃)。
注意:请参阅@wildplasser's answer此问题。老实说,这是最好的方法,因为它收紧了字符串指针数组和所述相同大小之间的关系。如果可以重新调整代码以使用该模型,那么您应该这样做,并且在这样做时选择该答案作为&#34;正确的&#34;溶液
答案 1 :(得分:2)
主要问题是您通过值将D
传递给函数:赋值
lexems = realloc(...);
对D
没有影响。在realloc
执行重新分配的情况下,D
成为悬空指针,因此取消引用它将成为未定义的行为。
您需要通过指针传递D
的方式与传递lexemsc
和&lexem_n
的方式相同,以便realloc
的效果在main
内可见{1}}功能也是如此。
此外,您的add_lexem
没有为要复制的字符串分配足够的内存:strlen
不计算空终止符,因此这两行
char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);
在分配的空间之后写一个字节'\0'
。
答案 2 :(得分:2)
避免三星级编程的替代方案:在结构中放置所需的一切:
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);
}
答案 3 :(得分:0)
问题可能来自:
char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);
尝试char *for_adding = malloc(sizeof(char) * (strlen(lexem)+1));
为&#39; \0
字符留出一些空间。
编辑:和@WhozCraig似乎是对的!
再见,