2015-02-04 2 views
1

Привет, у меня есть проблема, потому что я не понимаю, почему моя программа C имеет ошибку сегментации. Моя программа создает 2-мерный массив int, и каждая строка будет разделяться фиксированным размером 5, а случайные числа - в каждой строке. Но пользователь может выбрать, хочет ли он поставить более 5 строк в одну строку, если он захочет перевести мою линию. Длина каждой строки сохраняется в размере массива. Таким образом, выход прекрасен: для примера 1,6,3,4 8,6,5,3,2,1,6,8,9 1,4 8,9,6,4,2segmentation fault by realloc 2 dim array, но правый выход?

Но после выхода моя программа заканчивается ошибкой сегментации, но почему? это моя ошибка где-то в свободной функции или в моем выпуске? Спасибо за любой ответ и SRY за мой плохой английский :)

#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 eingeben\n"); 
      printf("1...Ja  0...Nein\n"); 
      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 eingegeben\n",j); 
      } 
      else{ 
       break; 
      } 
     } 
     size[i]=j; 
    } 
    printf("Your Numbers\n"); 
    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; 
} 
+0

Е ("Wollen Sie Noch Zahl сделайте Введите Ваше \ п «); Is printf («Вы хотите добавить число \ n») – rem

+0

printf («Sie haben schon% i Zahlen eingegeben \ n», j); Его информация о том, сколько номеров вы положили в одну строку – rem

+0

логически, 'arr [i] = (int *) malloc (sizeof (int *) * spalten);' должно быть 'arr [i] = malloc (sizeof (int) * spalten); ' –

ответ

0

Я думаю, проблема в

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

в вашем коде, вы выделили память только для 4 int * [int **arr=malloc(sizeof(int*)*4);], но позже в вашем коде вы увеличили значение spalten и позже, используя увеличивающееся значение при печати.

Там вы получаете доступ к внеочередной памяти, производящей неопределенное поведение.

вы должны изменить свой цикл печати на

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

PS - К сожалению, я тоже не носителем английского языка

+0

Ой так очевидно, спасибо большое;) теперь это работает :) – rem

+0

@rem Рад, что это помогло. Ура! :-) –

0
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 eingeben\n"); 
      printf("1...Ja  0...Nein\n"); 
      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 eingegeben\n",j); 
      } 

      else 
      { // else, user did not enter 1 ???? 
       break; 
      } // end if 
     } // end while 

     size[i]=j; // remember/ save meaningless number 
    } // end for 

    printf("Your Numbers\n"); 

    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 eingeben\n"); 
     printf("1...Ja  0...Nein\n"); 

     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 eingegeben\n",j); 
    } // end for 

    printf("Your Numbers\n"); 


    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