realloc 2 dim 数组的分段错误但输出正确?
segmentation fault by realloc 2 dim array but right output?
你好,我有一个问题,因为我不明白为什么我的 C 程序有段错误。我的程序创建了一个 2 dim int 数组,每一行都将按固定大小 5 分配,每行中都有随机数。但是如果他想重新分配我的行,用户可以选择是否要在一行中放置超过 5 个整数。每行长度都存储在数组大小中。所以输出很好:例如
1,6,3,4
8,6,5,3,2,1,6,8,9
1,4
8,9,6,4,2
但是在输出之后我的程序以分段错误结束但为什么呢?我的错误是在自由函数的某个地方还是在我的输出中?感谢您的回答,对不起我的英语不好 :)
#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;
}
我觉得,问题出在
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 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
你好,我有一个问题,因为我不明白为什么我的 C 程序有段错误。我的程序创建了一个 2 dim int 数组,每一行都将按固定大小 5 分配,每行中都有随机数。但是如果他想重新分配我的行,用户可以选择是否要在一行中放置超过 5 个整数。每行长度都存储在数组大小中。所以输出很好:例如 1,6,3,4 8,6,5,3,2,1,6,8,9 1,4 8,9,6,4,2
但是在输出之后我的程序以分段错误结束但为什么呢?我的错误是在自由函数的某个地方还是在我的输出中?感谢您的回答,对不起我的英语不好 :)
#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;
}
我觉得,问题出在
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 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