free():在tcache 2中检测到双释放在2d数组创建中已中止(核心转储)

vnzz0bqm  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(79)

我正在创建一个二维数组,它具有动态行和动态列大小。
我需要在主函数中分配内存。获取值,打印应该发生在不同的函数中
我的代码按照我的期望工作,但最后我得到了一个运行时错误free(): double free detected in tcache 2 Aborted (core dumped)
但是我在main中只使用了一个自由函数。这个错误的原因是什么?我使用的是gcc编译器。
执行示例:

代码:

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

void arr_value_getting_printing(int row,int col,int ** ptr)
{
    // Getting element from the user
    printf("Enter the elements:\n");
    for(int i = 0; i < row; i++)
    {
        for(int j = 0; j < col ; j++)
        {
            scanf("%d",&ptr[i][j]);
        }
    }
    

    // 2d array rows modification
    char ch;
    __fpurge(stdin);
    printf("Do you want to increase the Row(y/n):\n");
    scanf("%c",&ch);
    if(ch == 'y')
    {
    int new_row=0;
    printf("Enter the final row size (already 0 to %d row present):\n",row-1);
    scanf("%d",&new_row); 
    int**p =realloc(ptr, new_row * sizeof(int*));
    if (p != NULL)
    {
        ptr = p;
        // Getting the elements for the Newly created rows
        for(int i = row ; i < new_row ; i++ ) 
        {
            printf("Enter the elements for the new rows[%d]:",i);
            // Allocating memory for Newly created rows
            ptr[i] = calloc(col,sizeof(int)); 
            for(int j = 0; j < col ; j++)
            {
                scanf("%d",&ptr[i][j]);
            }
        }
        row = new_row;
    }   
    }

    // 2d array column modification
    __fpurge(stdin);
    // This arr pointer used for if any modification happens on any of the column it store the newly added column size
    int * arr = calloc(row,sizeof(int)); 
    printf("Do you want to increase the Col(y/n):\n");
    scanf("%c",&ch);
    while(ch == 'y')
    {
    int Row,Column;
    printf("Which Rows col you want to increase(Rows 0 - %d):\n",row-1);
    scanf("%d",&Row); // which row i need to modify
    printf("Enter the new col size(current col size %d):\n",col+arr[Row]);
    scanf("%d",&Column); // final column size
    int *temp = realloc (ptr[Row],Column); // roallocating
    if (temp != NULL)
    {
        ptr[Row] = temp;
        // updating the newly added column
        arr[Row] = Column - col; 
        printf("Enter the element for the new cols:\n");
        for(int j = col ; j < Column ; j++)
        {
            scanf("%d",&ptr[Row][j]);
        }
    }
    __fpurge(stdin);
    printf("Do you want to continue\n");
    scanf("%c",&ch);
    }

    // Printing the 2d array element
    printf("Printing the updated element array elenent:\n");
    for(int i = 0; i < row; i++)
    {
        for(int j = 0; j < col + arr[i] ; j++)
        {
            printf("%d ",ptr[i][j]);
        }
        printf("\n");
    }
}


int main()
{
    int row , col;
    printf("Enter the row and cols:\n");
    scanf("%d %d",&row,&col);
    int **ptr=calloc(row,sizeof(int*)); // 2d arr row creation 
    if (ptr != NULL)
    {
        for(int i = 0 ; i < row ; i++ )
        {
            ptr[i] = calloc(col,sizeof(int)); // 2d array column creation 
        } 

arr_value_getting_printing(row,col,ptr); //function call
    }
    free(ptr); // Freeing only one time
}

字符串

krugob8w

krugob8w1#

arr_value_getting_printing()中,当您使用realloc(ptr, ...)调整行数时,realloc()将在内部释放ptrA2),成功后,程序将新块的地址分配给ptrA4)..关键的见解是,变量是通过值传递的,因此main():ptrarr_value_getting_printing():ptr是两个不同的变量。仍然包含旧块A2的地址,因此free(ptr)将导致(A2的)双重空闲。
通常的方法是传入你试图修改的地址,但在这种情况下,它会导致被标记为3-星星程序员(不好)。返回更新的指针。调用者还需要新的行计数,所以我建议你传入rowcol的地址。
程序sorta支持每行的唯一列大小,但是你没有以调用者可以访问的方式存储这些列大小,所以我简化了你的程序,在所有行中使用1列大小。还将打印例程移动到调用者,只是为了显示它在那里工作。
更倾向于向sizeof传递一个变量而不是一个类型。这会导致更少的代码重复,并且它是变量的机械转换:

int *foo = malloc(sizeof *foo);
  int **bar = malloc(sizeof *bar);

字符串
(部分修复)检查所有malloc()calloc()realloc()调用的返回值。我认为使用calloc()作为指针是个好主意,但个别值被覆盖,因此malloc()更有意义。错误处理代码现在返回到调用者,而不是继续。
(Not fixed)检查new_row和new_col是否更大(以匹配提示符)。在main()中,您要检查row > 0col > 0作为零大小数组是否未定义。
(Not检查所有scanf()调用的返回值,否则您可能正在操作未初始化的变量。

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

int **arr_value_getting_printing(int *row, int *col, int **ptr) {
    printf("Enter the elements:\n");
    for(int r = 0; r < *row; r++)
        for(int c = 0; c < *col ; c++)
            scanf("%d",&ptr[r][c]);

    __fpurge(stdin);
    printf("Do you want to increase the Row(y/n):\n");
    char ch;
    scanf("%c",&ch);
    if(ch == 'y') {
        printf("Enter the final row size (already 0 to %d row present):\n", *row-1);
        int new_row;
        scanf("%d", &new_row);
        int **p = realloc(ptr, new_row * sizeof *p);
        if (!p) {
            fprintf(stderr, "realloc failed\n");
            return ptr;
        }
        ptr = p;
        for(int r = *row ; r < new_row ; r++ ) {
            printf("Enter the elements for the new rows[%d]:", r);
            ptr[r] = malloc(*col * sizeof *ptr[r]);
            for(int c = 0; c < *col ; c++)
                scanf("%d",&ptr[r][c]);
        }
        *row = new_row;
    }

    __fpurge(stdin);
    printf("Do you want to increase the Col(y/n):\n");
    scanf("%c",&ch);
    if(ch == 'y') {
        int new_col;
        printf("Enter the new col size (current col size %d):\n", *col);
        scanf("%d",&new_col);
        printf("Enter the element for the new cols:\n");
        for(int r = 0; r < *row; r++) {
            int *p = realloc(ptr[r], sizeof *p * new_col);
            if(!p) {
                fprintf(stderr, "realloc failed\n");
                // note some columns may be *col others new_col,
                // so better approach is probably to free all
                // rows and ptr and return NULL.
                return ptr;
            }
            ptr[r] = p;
            for(int c = *col; c < new_col; c++)
                scanf("%d", &ptr[r][c]);
        }
        *col = new_col;
    }
    return ptr;
}

int main(void) {
    printf("Enter the row and cols:\n");
    int row , col;
    scanf("%d %d",&row,&col);
    int **ptr = calloc(row, sizeof *ptr);
    if (!ptr) {
        fprintf(stderr, "calloc() failed\n");
        return 1;
    }
    for(int i = 0 ; i < row ; i++ )
        ptr[i] = malloc(col * sizeof *ptr[i]);
    ptr = arr_value_getting_printing(&row, &col, ptr);

    printf("Printing the updated element array elenent:\n");
    for(int r = 0; r < row; r++) {
        for(int c = 0; c < col; c++)
            printf("%d%c", ptr[r][c], c + 1 < col ? ' ' : '\n');
        free(ptr[r]);
    }
    free(ptr);
}


示例运行:

Enter the row and cols:
2 2
Enter the elements:
1 2 3 4
Do you want to increase the Row(y/n):
y
Enter the final row size (already 0 to 1 row present):
3
Enter the elements for the new rows[2]:5 6
Do you want to increase the Col(y/n):
y
Enter the new col size (current col size 2):
3
Enter the element for the new cols:
7 8 9
Printing the updated element array element:
1 2 7
3 4 8
5 6 9


Valgrind很高兴:

==396782== All heap blocks were freed -- no leaks are possible

相关问题