【问题标题】:Gradually reallocating of memory leads to segmentation fault逐渐重新分配内存会导致分段错误
【发布时间】:2020-11-04 20:04:45
【问题描述】:

我正在尝试将新值附加到另一个函数中的 c 字符串数组,但是我只能添加三个记录,当我尝试添加第四个条目等等时,会发生段错误的错误,这告诉我我使用了错误的记忆。据我了解,我逐渐按需将内存分配为 realloc(array, array_length * sizeof(char)) 所以它应该没问题,但事实并非如此。此外,当我尝试在 main() 函数中追加新记录时,它会按预期运行 10 条记录。

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

int array_length = 0;

void add(char **array, char *new)
{
    array_length++;
    array = realloc(*array, array_length * sizeof(char*));
    array[array_length-1] = malloc(50 * sizeof(char*));
    strcpy(array[array_length-1], new);
}

int main() 
{
    char **array = malloc (sizeof (*array));

    // First way
    add(&array, "first str");    // fine
    add(&array, "second str");   // fine
    add(&array, "third str");    // fine
    //add(&array, "fourth str"); // Segmentation fault (core dumped)    
    
    // Second way: 10 records successfully appended to array
    // for (int i = 0; i < 10; i++)
    // {
    //     array_length++;
    //     array = realloc(array, array_length * sizeof(char*));
    //     array[array_length-1] = malloc(50 * sizeof(char*));
    //     strcpy(array[array_length-1], "str");
    // }

    for (int i = 0; i < array_length; i++)
        printf("%s\n", array[i]);
    
    for (int j = 0; j < array_length; j++)
        free(array[j]);
    free(array);

    return 0;
}

【问题讨论】:

  • 嗯......我注意到的第一件事是类型不匹配。在main() 中,您将array 定义为char**,然后将其地址(char*** 类型)传递给add(),但后面的函数接受char** 类型的参数。
  • 如果你启用了所有警告和错误,你的编译器可能会有already shown you where the problem is。首先,如果它应该表示一个字符串数组,那么主函数中的array 应该是char ** 类型。然后你传递一个指向这个变量的指针,以便realloc 可以改变它,所以add 必须接受char ***。其次,realloc 的语法是x = realloc(x, new_length);,或者在本例中为*array = realloc(*array, ...)
  • @Groo,感谢您的指出,但即使进行了这些更改,第 4 个元素仍会出现段错误
  • @user3121023,如果我将数组声明从 char **array = malloc (sizeof (*array)); 更改为有效to char ***array = malloc (sizeof (*array));我想它是通过 id 指向字符串的内存地址的指针?如果我调用 add 作为 add(array, "first str");不提供数组地址。最后释放内存会再次导致段错误

标签: c segmentation-fault realloc


【解决方案1】:

您需要在add 函数中区分char*char**char***。也许一个好方法是将参数命名为pArray 以跟踪正在发生的事情:

int array_length = 0;

void add(char *** pArray, const char * new_val)
{
    array_length++;

    // we are modifying the original 'array' variable, 
    // so we need to assign the result to *pArray
    // (also note the sizeof used here)
    *pArray = realloc(*pArray, array_length * sizeof(char**));

    // from now on, we don't need to mutate the original variable,
    // so dereference 'pArray' into 'array'
    char ** array = *pArray;
    array[array_length - 1] = malloc(50 * sizeof(char));
    strcpy_s(array[array_length - 1], 49, new_val);
}

如果你想避免三星级的东西,考虑将数组包装成一个结构。这也更好,因为array_length 不应该是全局变量。

例如:

typedef struct
{
    char ** array;
    size_t array_length;
}
string_list;

void add(string_list * s, const char * new_val)
{
    s->array_length++;
    s->array = realloc(s->array, s->array_length * sizeof(char**));

    s->array[s->array_length - 1] = malloc(50 * sizeof(char));
    strcpy_s(s->array[s->array_length - 1], 49, new_val);
}

void string_list_init(string_list * s)
{
    s->array = NULL;
    s->array_length = 0;
}

然后简单地说:

string_list s;
string_list_init(&s);

// First way
add(&s, "first str");    // fine
add(&s, "second str");   // fine
add(&s, "third str");    // fine
add(&s, "fourth str"); // Segmentation fault (core dumped)   

【讨论】:

    猜你喜欢
    • 2017-11-21
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多