realloc 2 dim数组c分割错误,但输出正确



嗨,我有一个问题,因为我不明白为什么我的C程序有分段错误。我的程序创建了一个2 dim int数组,每一行都将被固定大小为5的mallocated,并且每一行中都有随机数。但是用户可以选择他是否想在一行中放入5个以上的整数,如果他想重新分配我的行。每个行长度都存储在数组大小中。因此输出很好:例如1,6,3,48,6,5,3,2,6,8,91,48,9,6,4,2

但在输出后,我的程序以分段错误结束,但为什么??我的错误是在free函数中还是在我的输出中??谢谢你的回答,谢谢我糟糕的英语:)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void flushi(){// to flush the buffer 
char buff = ' ';
    while ((buff = getchar()) != 'n' &&buff !=EOF);
    return;
}
void freeall(int **arr,int zeilen){
    for (int i = 0; i < zeilen; i++) { 
        free(arr[i]);
    }
    free(arr);
}
int main(){
    int zeilen=4;
    int d,j;
    srand(time(0));
    int spalten=5;
    int size[spalten];
    int **arr=malloc(sizeof(int*)*4);
    for(int i=0;i<zeilen;i++){
        arr[i]=(int*)malloc(sizeof(int*)*spalten);// malloc first line
        j=0;
        while(1){
            printf("Wollen sie noch eine Zahl eingebenn");
            printf("1...Ja      0...Neinn");
            scanf("%i",&d);
            flushi();
            if(d==1){
                if(j>=spalten){// if user want more than 5 int in one line
                    spalten++;
                    arr[i]=realloc(arr[i],sizeof(int)*spalten);// realloc line
                }
                arr[i][j]= (rand()%10)+1;
                j++;
                printf("Sie haben schon %i Zahlen eingegebenn",j);
            }
            else{
                break;
            }
        }
        size[i]=j;
    }
    printf("Your Numbersn");
    for (int h=0;h<spalten;h++){
        printf("n");
        for (int g=0;g<size[h];g++){
            printf("%i ",arr[h][g]);
        }
    }
    printf("n");
    freeall(arr,zeilen);
    return EXIT_SUCCESS;
}

我认为问题出在

for (int h=0;h<spalten;h++)

在代码中,您只为4个int *[int **arr=malloc(sizeof(int*)*4);]分配了内存,但在代码的后面,您增加了spalten,然后在打印中使用增加的值。

在那里,您正在访问超出限制的内存,从而产生未定义的行为。

您应该将打印循环更改为

for (int h=0;h<4;h++)

p.S-对不起,我也不是以英语为母语的人

There are several problems.
I have added comments about some of the problems to the original code
Please comment your code, for two major reasons
1) so in a few months you do not have to reverse engineer the code
2) so I do not have to reverse engineer your code 
   so that I can helpfully comment on what went wrong in the code
Note: getchar returns a int value, not a char value
      and 'n' on certain OSs is 2 characters
      and EOF is -1, not a char
The second code group is a suggested fix
In the second code group, there are certain improvements
that could be easily made,  
For instance, eliminate the spalen variable
allocate for the rows only once via:
if user enters 0,  
then use the default length, 
otherwise the user entered length

----Original code group with some comments----
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void flushi()
{// to flush the buffer 
    char buff = ' ';
    while ((buff = getchar()) != 'n' &&buff !=EOF);
} // end function: flushi

void freeall(int **arr,int zeilen)
{
    for (int i = 0; i < zeilen; i++)
    { 
        free(arr[i]);
    }
    free(arr);
} // end function: freeall

int main()
{
    int zeilen=4;
    int d,j;
    srand(time(0)); // should be srand( time( NULL ) );
    int spalten=5;
    int size[spalten];
    int **arr=malloc(sizeof(int*)*4); // allocate room for 4 pointers to integers
       // should always test returned value from malloc to assure operation successful
    for(int i=0;i<zeilen;i++) // foreach of the 4 pointers to integers
    {
        arr[i]=(int*)malloc(sizeof(int*)*spalten);// ERROR: allocate room for 5 pointers to intege
             // should be: arr[i] = malloc( sizeof(int)*spalten); // allocate room for 5 integers
             // should always test returned value from malloc to assure operation successful
        j=0;
        while(1)
        {
            printf("Wollen sie noch eine Zahl eingebenn");
            printf("1...Ja      0...Neinn");
            scanf("%i",&d);
                // should always test returned value from scanf to assure operation successful
            flushi();
            if(d==1) // 
            {
                if(j>=spalten)
                {// if user want more than 5 int in one line
                    spalten++;
                    arr[i]=realloc(arr[i],sizeof(int)*spalten);// realloc line
                        // always test returned value from realloc before
                        // 1) to assure operation was successful
                        // 2) before using the new pointer
                        //    otherwise old allocation lost, resulting in a memory leak
                } // end if
                arr[i][j]= (rand()%10)+1;
                j++;
                printf("Sie haben schon %i Zahlen eingegebenn",j);
            }
            else
            { // else, user did not enter 1 ????
                break;
            } // end if
        } // end while
        size[i]=j; // remember/ save meaningless number
    } // end for
    printf("Your Numbersn");
    for (int h=0;h<spalten;h++) // foreach 0...4
    {
        printf("n");
        for (int g=0;g<size[h];g++) // for each 0...meaningless value
        {
            printf("%i ",arr[h][g]);
        } // end if
    } // end for
    printf("n");
    freeall(arr,zeilen);
    return EXIT_SUCCESS;
} // end function: main
----second code group which is a suggested fix----
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
void flushi()
{// to flush the buffer
    int buff;
    while ((buff = getchar()) != 'n' &&buff !=EOF);
} // end function: flushi

void freeall(int **arr,int rowCount)
{
    // free each row
    for (int i = 0; i < rowCount; i++)
    {
        free(arr[i]); // note: ok to call free() with null pointer
    }
    // free the array
    free(arr);
} // end function: freeall

#define MAX_ROWS (4)
#define DEFAULT_ROW_LEN (5)
// notice the removal of unneeded variables
// notice that most features are implemented 
// in separate code blocks
int main()
{
    int rowLength;  // new length (of integers) for each row
    int i, j;       // loop index/counters
    int spalten=DEFAULT_ROW_LEN;  // default length (of integers) for each row
    int size[MAX_ROWS] = {0};  // save area for final length of each row
    int **arr = NULL;
    if( NULL == (arr=malloc(sizeof(int*)*MAX_ROWS) ) ) // allocate room for MAX_ROWS pointers to integers
    { // then malloc failed
        perror( "malloc failed for number of rows" );
        exit( EXIT_FAILURE );
    }
    // implied else, malloc successful
    // clear first memory allocation (int pointers) to NULLs
    memset( arr, 0x00, MAX_ROWS*sizeof(int*) );
    for(i=0; i<MAX_ROWS; i++) // foreach of the rows
    {
        if( NULL == (arr[i]=malloc(sizeof(int)*spalten) ) )
        { // then, malloc failed
            perror( "malloc failed for row" );
            freeall( arr, MAX_ROWS ); // cleanup
            exit( EXIT_FAILURE );
        }
        // implied else, malloc successful
        size[i] = spalten;
    } // end for each row
    srand( time( NULL ) );
    for( i=0; i<MAX_ROWS; i++) // foreach row
    {
        printf("Wollen sie noch eine Zahl eingebenn");
        printf("1...Ja      0...Neinn");
        if( 1 != scanf("%i",&rowLength) )
        { // then scanf failed
            perror( "scanf failed for row length" );
            freeall( arr, MAX_ROWS ); // cleanup
            exit( EXIT_FAILURE );
        }
        // implied else, scanf successful
        flushi();
        if( rowLength > 0) // 0 means no change and negative numbers are ignored
        { // then, user wants a different length for this row
            if(rowLength != spalten)
            {
                size[i] = rowLength;
                int * temp;
                // if user want other than 5 int in one row
                if( NULL == (temp = realloc(arr[i],sizeof(int)*rowLength) ) )
                { // then, realloc failed
                    perror( "realloc failed for row length change" );
                    freeall( arr, MAX_ROWS ); // cleanup
                    exit( EXIT_FAILURE );
                }
                // implied else, realloc successful
                arr[i] = temp; // update the pointer in the array
            } // end if
        } // end if
        // fill in row of arr with random values
        for( j = 0; j<size[i]; j++ )
        {
            arr[i][j]= (rand()%10)+1;
        } // end if
        printf("Sie haben schon %i Zahlen eingegebenn",j);
    } // end for
    printf("Your Numbersn");

    for (int i=0;i<MAX_ROWS;i++) // foreach row
    {
        printf("n");
        for (int j=0;j<size[i];j++)
        {
            printf("%i ",arr[i][j]);
        } // end if
    } // end for
    printf("n");
    freeall(arr,MAX_ROWS); // cleanup
    return EXIT_SUCCESS;
} // end function: main

相关内容

  • 没有找到相关文章

最新更新