【问题标题】:How to correctly dynamically allocate memory?如何正确动态分配内存?
【发布时间】:2017-06-13 14:11:03
【问题描述】:

以下代码取自本网站的示例。我不明白,我做错了什么?你能帮帮我吗?

编译:

gcc -std=c11 main.c

仅打印:

东西:煮荞麦,重量:1500

分段错误

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

typedef struct {
    // Weight in grams
    size_t weight;
    // Name of Thing
    char name[255];

} Things;

void add_new_thing(Things **things,size_t *size)
{

    size_t index = *size;

    if(index == 0){
        (*size) = 1;
        *things = (Things*)calloc((*size),sizeof(Things));
        if (*things == NULL) {
            fprintf(stderr, "Error: can't allocate memory! %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
    }else{
        (*size) += 1;
        Things *temp = (Things*)realloc(*things,(*size)*sizeof(Things));
        if(temp != NULL) {
            *things = temp;
        }else{
            fprintf(stderr, "Error: can't reallocate memory! %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }
        // Zeroing of new structure's elements
        things[index]->name[0] = '\0';
        things[index]->weight = 0;
    }

}

void another_function(Things *things,size_t *size)
{
    // Add one element to the array of structures
    add_new_thing(&things,size);
    const char *str1 = "Boiled buckwheat";
    strncpy(things[*size-1].name, str1, strlen(str1) + 1);
    things[*size-1].weight = 1500;

    for(size_t i = 0;i < *size;i++){
        printf("Thing: %s, weight: %zu\n",things[i].name,things[i].weight);
    }

    // Add one more element to the array of structures
    add_new_thing(&things,size);
    const char *str2 = "A toy";
    strncpy(things[*size-1].name, str2, strlen(str2) + 1);
    things[*size-1].weight = 350;

    // Segmentation fault is below
    for(size_t i = 0;i < *size;i++){
        printf("Thing: %s, weight: %zu\n",things[i].name,things[i].weight);
    }
}

void some_function(Things *things,size_t *size)
{
    // To pass the array of structures to another function
    another_function(things,size);
}

int main(void)
{

    // Create NULL pointer for the array of structures
    Things *things = NULL;

    // Add size of structures' array which will be allocated within add_new_thing() function
    size_t size = 0;

    // Call some function
    some_function(things,&size);

    // Segmentation fault is below
    printf("Print results:\n");
    for(size_t i = 0;i < size;i++){
        printf("Thing: %s, weight: %zu\n",things[i].name,things[i].weight);
    }

    free(things);

    return(EXIT_SUCCESS);
}

【问题讨论】:

标签: c arrays struct segmentation-fault dynamic-allocation


【解决方案1】:

请记住,C 有按值调用,这意味着在main 函数中,您将things 中的空指针的副本传递给some_functionmain 中的实际变量不会改变。

只有在another_function 中,您才模拟通过引用传递,并且只有在another_function 中,things 变量才会被add_new_thing 中的分配更新。

【讨论】:

    【解决方案2】:

    真正的问题在这里

    // Zeroing of new structure's elements
    things[index]->name[0] = '\0';
    things[index]->weight = 0;
    

    必须是

    (*things)[index].name[0] = '\0';
    (*things)[index].weight = 0;
    

    因为,things不是指针的指针,而只是一个指针。

    您将things 视为指向指针数组的指针,但它只是指向Things 的“array”的指针。我说“array ”,因为严格来说它不是数组,数组在 c 中是不同的东西。但它在所有方面都与数组相同。

    您也在 main 中创建了指针,但您从未正确使用该指针的副本,您仍然 free() 它。

    尝试阅读更正后的代码,看看你是否能理解你的错误

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    typedef struct
    {
        // Weight in grams
        size_t weight;
        // Name of Thing
        char name[255];
    
    } Things;
    
    void add_new_thing(Things **things,size_t *size)
    {
    
        size_t index = *size;
    
        if(index == 0)
            {
                (*size) = 1;
                *things = (Things*)calloc((*size),sizeof(Things));
                if (*things == NULL)
                    {
                        fprintf(stderr, "Error: can't allocate memory! %s\n", strerror(errno));
                        exit(EXIT_FAILURE);
                    }
            }
        else
            {
                (*size) += 1;
                Things *temp = (Things*)realloc(*things,(*size)*sizeof(Things));
                if(temp != NULL)
                    {
                        *things = temp;
                    }
                else
                    {
                        fprintf(stderr, "Error: can't reallocate memory! %s\n", strerror(errno));
                        exit(EXIT_FAILURE);
                    }
                // Zeroing of new structure's elements
                (*things)[index].name[0] = '\0';
                (*things)[index].weight = 0;
            }
    
    }
    
    void another_function(Things **things, size_t *size)
    {
        // Add one element to array of structures
        add_new_thing(things,size);
        const char *str1 = "Boiled buckwheat";
        strncpy((*things)[*size-1].name, str1, strlen(str1) + 1);
        (*things)[*size-1].weight = 1500;
    
        for(size_t i = 0; i < *size; i++)
            {
                printf("Thing: %s, weight: %zu\n",(*things)[i].name,(*things)[i].weight);
            }
        // One element of array of structures was printed there
    
        // Add new one element to array of structures
        add_new_thing(things, size);
        const char *str2 = "A toy";
        strncpy((*things)[*size-1].name, str2, strlen(str2) + 1);
        (*things)[*size-1].weight = 350;
    
        // Segmentation fault is there
        for(size_t i = 0; i < *size; i++)
            {
                printf("Thing: %s, weight: %zu\n",(*things)[i].name,(*things)[i].weight);
            }
    }
    
    void some_function(Things **things, size_t *size)
    {
        // Pass array of structures to another function
        another_function(things, size);
    }
    
    int main(void)
    {
    
        // Create NULL pointer for array of structures
        Things *things = NULL;
    
        // And size of structures array which will be allocated within add_new_thing() function
        size_t size = 0;
    
        // Call some function
        some_function(&things, &size);
    
        // Segmentation fault is there
        printf("Print results:\n");
        for(size_t i = 0; i < size; i++)
            {
                printf("Thing: %s, weight: %zu\n",things[i].name,things[i].weight);
            }
        free(things);
    
        return(EXIT_SUCCESS);
    }
    

    【讨论】:

    • 非常感谢您的详细解释。我是 C 的新手。我只学了三年。 )
    【解决方案3】:

    在您的主函数中,您将things(即NULL)的值传递给函数some_function()。所以这个指针没有改变,你需要传递它的地址。 printf() 调用尝试访问以 NULL 存储的内容。 (显然这是不可能的)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 2013-09-27
      • 1970-01-01
      • 2017-05-08
      • 1970-01-01
      • 1970-01-01
      • 2017-06-06
      相关资源
      最近更新 更多