C:如果调用顺序改变,使用结构的嵌套函数会破坏程序
C: Nested functions using structs break the program if order of call is changed
我在编程练习中遇到了一个问题,我找不到问题的根源,因为程序是用
gcc -std=c11 -Wall -Wextra -Wpedantic test.c -o test.exe
没有错误也没有标志。
当 square_matrix_multiplication
的调用放在 triagonal_invert
函数的末尾时会出现特定问题(完整代码在末尾):
Square_Matrix tridigonal_invert(Square_Matrix matrix){
int dim = matrix.n;
double factor;
Square_Matrix inverse = {dim, calloc(dim*dim,sizeof(double))};
for(int i = 0;i<dim;i++){
inverse.data[i+dim*i]=i;
}
Square_Matrix lower = {dim, calloc(dim*dim,sizeof(double))};
Square_Matrix upper = {dim, calloc(dim*dim,sizeof(double))};
// here works:
print_square_matrix(square_matrix_multiplication(inverse,lower));
//###############################################################
lower.data[0]=1;
upper.data[0]=matrix.data[0];
upper.data[1]=matrix.data[1];
for(int i = 1 ; i< dim; i++){
lower.data[i+i*dim]=1;
lower.data[i-1+i*dim]=matrix.data[i-1+i*dim]/upper.data[(i-1)+(i-1)*dim];
upper.data[i+i*dim]=matrix.data[i+i*dim]-lower.data[i-1+i*dim]*matrix.data[i+(i-1)*dim];
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
for(int j =0; j<i;j++){
inverse.data[j+i*dim]=1;
for(int k=j;k<i;k++){
inverse.data[j+i*dim]*=-1*lower.data[k+(k+1)*dim];
}
}
/* factor=-1*lower.data[i-1+i*dim];
for(int j=0;j<i;j++){
lower.data[j+i*dim]=factor*lower.data[j+(i-1)*dim];
}*/
}
for(int i = dim-1;i>=0;i--){
upper.data[i+dim*i]=1/upper.data[i+i*dim];
factor=-1*upper.data[i+dim*i]*upper.data[i+1+i*dim];
for(int j=i+1;j<dim;j++){
upper.data[j+i*dim]=factor*upper.data[j+(i+1)*dim];
}
}
// here does not work:
print_square_matrix(square_matrix_multiplication(inverse,lower));
//###############################################################
print_square_matrix(upper);
print_square_matrix(inverse);
}
编辑 澄清问题:
如果调用 print_square_matrix(square_matrix_multiplication(inverse,lower));
发生在第二个 for
语句之后,程序将在函数调用无误退出时停止。
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef struct
{
int n;
double *data;
} Square_Matrix;
typedef struct {
int lenght;
double *data;
} n_vector;
void print_square_matrix(Square_Matrix matrix){
int dim= matrix.n;
printf("%dx%d Matrix\n",dim,dim);
for(int i = 0;i<dim*dim;i++){
printf("%lf ",matrix.data[i]);
if((i+1)%dim==0){
printf("\n");
}
}
}
void print_n_vector(n_vector vector){
int dim = vector.lenght;
for( int i=0; i<dim; i++){
printf("%lf \n",vector.data[i]);
}
}
void print_matrix_vector(Square_Matrix matrix,n_vector vector){
int dim= matrix.n;
int count = 0;
printf("MATRIX|VECTOR\n");
for(int i = 0;i<dim*dim;i++){
printf("%lf ",matrix.data[i]);
if((i+1)%dim==0){
printf(" %lf \n",vector.data[count]);
count+=1;
}
}
}
Square_Matrix square_matrix_multiplication(Square_Matrix matrix1, Square_Matrix matrix2){
int dim= matrix1.n;
Square_Matrix result={dim,calloc(dim*dim,sizeof(double))};
for(int i=0; i<dim;i++){
for(int j = 0; j<dim; j++){
for(int k=0;k<dim;k++){
result.data[j+i*dim]+=matrix1.data[k+i*dim]*matrix2.data[j+k*dim];
}
}
}
return result;
}
n_vector tridiagonal_solve(Square_Matrix matrix, n_vector vector){
int dim = matrix.n;
Square_Matrix lower = {dim, calloc(dim*dim,sizeof(double))};
Square_Matrix upper = {dim, calloc(dim*dim,sizeof(double))};
n_vector result = vector;
lower.data[0]=1;
upper.data[0]=matrix.data[0];
upper.data[1]=matrix.data[1];
for(int i = 1 ; i< dim; i++){
lower.data[i+i*dim]=1;
lower.data[i-1+i* dim]=matrix.data[i-1+i*dim]/upper.data[(i-1)+(i-1)*dim];
upper.data[i+i*dim]=matrix.data[i+i*dim]-lower.data[i-1+i*dim]*matrix.data[i+(i-1)*dim];
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
result.data[i]= result.data[i]-lower.data[i-1+i*dim]*result.data[i-1];
}
result.data[dim-1]/= upper.data[dim*dim-1];
for (int i = dim-2; i>=0; i--)
{
result.data[i]=(result.data[i]-upper.data[i+1+i*dim]*result.data[i+1])/upper.data[i+i*dim];
}
return result;
}
Square_Matrix tridigonal_invert(Square_Matrix matrix){
int dim = matrix.n;
double factor;
Square_Matrix inverse = {dim, calloc(dim*dim,sizeof(double))};
for(int i = 0;i<dim;i++){
inverse.data[i+dim*i]=i;
}
Square_Matrix lower = {dim, calloc(dim*dim,sizeof(double))};
Square_Matrix upper = {dim, calloc(dim*dim,sizeof(double))};
lower.data[0]=1;
upper.data[0]=matrix.data[0];
upper.data[1]=matrix.data[1];
for(int i = 1 ; i< dim; i++){
lower.data[i+i*dim]=1;
lower.data[i-1+i*dim]=matrix.data[i-1+i*dim]/upper.data[(i-1)+(i-1)*dim];
upper.data[i+i*dim]=matrix.data[i+i*dim]-lower.data[i-1+i*dim]*matrix.data[i+(i-1)*dim];
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
for(int j =0; j<i;j++){
inverse.data[j+i*dim]=1;
for(int k=j;k<i;k++){
inverse.data[j+i*dim]*=-1*lower.data[k+(k+1)*dim];
}
}
/* factor=-1*lower.data[i-1+i*dim];
for(int j=0;j<i;j++){
lower.data[j+i*dim]=factor*lower.data[j+(i-1)*dim];
}*/
}
for(int i = dim-1;i>=0;i--){
upper.data[i+dim*i]=1/upper.data[i+i*dim];
factor=-1*upper.data[i+dim*i]*upper.data[i+1+i*dim];
for(int j=i+1;j<dim;j++){
upper.data[j+i*dim]=factor*upper.data[j+(i+1)*dim];
}
}
print_square_matrix(square_matrix_multiplication(inverse,lower));
print_square_matrix(upper);
print_square_matrix(inverse);
}
int main(){
Square_Matrix newMatrix={4,calloc(16,sizeof(double))};
Square_Matrix index = {4,calloc(16,sizeof(double))};
for(int i=0;i<4;i++){
index.data[i+4*i]=1;
}
n_vector vector={4,calloc(4,sizeof(double))};
memcpy(newMatrix.data, (double[]){ 2,-1, 0, 0,
-1, 2,-1, 0,
0,-1, 2,-1,
0, 0, -1, 2},16 * sizeof(double));
memcpy(vector.data, (double[]){-5, 1, 4, 1},4*sizeof(double));
tridigonal_invert(newMatrix);
//index=square_matrix_multiplication(newMatrix,index);
//print_square_matrix(index);
free(newMatrix.data);
free(vector.data);
free(index.data);
//print_square_matrix(index);
//print_square_matrix(square_matrix_multiplication(newMatrix,index));
/*vector = tridiagonal_solve(newMatrix,vector);
print_n_vector(vector);*/
}
这一行在tridigonal_invert
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
在 i == 3
时超出两个内存区域的范围,调用未定义的行为。 dim == 4
,upper
和 matrix
都有 space 保留 16 double
秒(有效索引 [0, 15]),但是当 i == 3
在此循环中,i+1+i*dim == 16
,超出范围 1.
也可能存在其他越界情况,建议在 valgrind 中 运行 尝试识别它们。
我在编程练习中遇到了一个问题,我找不到问题的根源,因为程序是用
gcc -std=c11 -Wall -Wextra -Wpedantic test.c -o test.exe
没有错误也没有标志。
当 square_matrix_multiplication
的调用放在 triagonal_invert
函数的末尾时会出现特定问题(完整代码在末尾):
Square_Matrix tridigonal_invert(Square_Matrix matrix){
int dim = matrix.n;
double factor;
Square_Matrix inverse = {dim, calloc(dim*dim,sizeof(double))};
for(int i = 0;i<dim;i++){
inverse.data[i+dim*i]=i;
}
Square_Matrix lower = {dim, calloc(dim*dim,sizeof(double))};
Square_Matrix upper = {dim, calloc(dim*dim,sizeof(double))};
// here works:
print_square_matrix(square_matrix_multiplication(inverse,lower));
//###############################################################
lower.data[0]=1;
upper.data[0]=matrix.data[0];
upper.data[1]=matrix.data[1];
for(int i = 1 ; i< dim; i++){
lower.data[i+i*dim]=1;
lower.data[i-1+i*dim]=matrix.data[i-1+i*dim]/upper.data[(i-1)+(i-1)*dim];
upper.data[i+i*dim]=matrix.data[i+i*dim]-lower.data[i-1+i*dim]*matrix.data[i+(i-1)*dim];
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
for(int j =0; j<i;j++){
inverse.data[j+i*dim]=1;
for(int k=j;k<i;k++){
inverse.data[j+i*dim]*=-1*lower.data[k+(k+1)*dim];
}
}
/* factor=-1*lower.data[i-1+i*dim];
for(int j=0;j<i;j++){
lower.data[j+i*dim]=factor*lower.data[j+(i-1)*dim];
}*/
}
for(int i = dim-1;i>=0;i--){
upper.data[i+dim*i]=1/upper.data[i+i*dim];
factor=-1*upper.data[i+dim*i]*upper.data[i+1+i*dim];
for(int j=i+1;j<dim;j++){
upper.data[j+i*dim]=factor*upper.data[j+(i+1)*dim];
}
}
// here does not work:
print_square_matrix(square_matrix_multiplication(inverse,lower));
//###############################################################
print_square_matrix(upper);
print_square_matrix(inverse);
}
编辑 澄清问题:
如果调用 print_square_matrix(square_matrix_multiplication(inverse,lower));
发生在第二个 for
语句之后,程序将在函数调用无误退出时停止。
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef struct
{
int n;
double *data;
} Square_Matrix;
typedef struct {
int lenght;
double *data;
} n_vector;
void print_square_matrix(Square_Matrix matrix){
int dim= matrix.n;
printf("%dx%d Matrix\n",dim,dim);
for(int i = 0;i<dim*dim;i++){
printf("%lf ",matrix.data[i]);
if((i+1)%dim==0){
printf("\n");
}
}
}
void print_n_vector(n_vector vector){
int dim = vector.lenght;
for( int i=0; i<dim; i++){
printf("%lf \n",vector.data[i]);
}
}
void print_matrix_vector(Square_Matrix matrix,n_vector vector){
int dim= matrix.n;
int count = 0;
printf("MATRIX|VECTOR\n");
for(int i = 0;i<dim*dim;i++){
printf("%lf ",matrix.data[i]);
if((i+1)%dim==0){
printf(" %lf \n",vector.data[count]);
count+=1;
}
}
}
Square_Matrix square_matrix_multiplication(Square_Matrix matrix1, Square_Matrix matrix2){
int dim= matrix1.n;
Square_Matrix result={dim,calloc(dim*dim,sizeof(double))};
for(int i=0; i<dim;i++){
for(int j = 0; j<dim; j++){
for(int k=0;k<dim;k++){
result.data[j+i*dim]+=matrix1.data[k+i*dim]*matrix2.data[j+k*dim];
}
}
}
return result;
}
n_vector tridiagonal_solve(Square_Matrix matrix, n_vector vector){
int dim = matrix.n;
Square_Matrix lower = {dim, calloc(dim*dim,sizeof(double))};
Square_Matrix upper = {dim, calloc(dim*dim,sizeof(double))};
n_vector result = vector;
lower.data[0]=1;
upper.data[0]=matrix.data[0];
upper.data[1]=matrix.data[1];
for(int i = 1 ; i< dim; i++){
lower.data[i+i*dim]=1;
lower.data[i-1+i* dim]=matrix.data[i-1+i*dim]/upper.data[(i-1)+(i-1)*dim];
upper.data[i+i*dim]=matrix.data[i+i*dim]-lower.data[i-1+i*dim]*matrix.data[i+(i-1)*dim];
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
result.data[i]= result.data[i]-lower.data[i-1+i*dim]*result.data[i-1];
}
result.data[dim-1]/= upper.data[dim*dim-1];
for (int i = dim-2; i>=0; i--)
{
result.data[i]=(result.data[i]-upper.data[i+1+i*dim]*result.data[i+1])/upper.data[i+i*dim];
}
return result;
}
Square_Matrix tridigonal_invert(Square_Matrix matrix){
int dim = matrix.n;
double factor;
Square_Matrix inverse = {dim, calloc(dim*dim,sizeof(double))};
for(int i = 0;i<dim;i++){
inverse.data[i+dim*i]=i;
}
Square_Matrix lower = {dim, calloc(dim*dim,sizeof(double))};
Square_Matrix upper = {dim, calloc(dim*dim,sizeof(double))};
lower.data[0]=1;
upper.data[0]=matrix.data[0];
upper.data[1]=matrix.data[1];
for(int i = 1 ; i< dim; i++){
lower.data[i+i*dim]=1;
lower.data[i-1+i*dim]=matrix.data[i-1+i*dim]/upper.data[(i-1)+(i-1)*dim];
upper.data[i+i*dim]=matrix.data[i+i*dim]-lower.data[i-1+i*dim]*matrix.data[i+(i-1)*dim];
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
for(int j =0; j<i;j++){
inverse.data[j+i*dim]=1;
for(int k=j;k<i;k++){
inverse.data[j+i*dim]*=-1*lower.data[k+(k+1)*dim];
}
}
/* factor=-1*lower.data[i-1+i*dim];
for(int j=0;j<i;j++){
lower.data[j+i*dim]=factor*lower.data[j+(i-1)*dim];
}*/
}
for(int i = dim-1;i>=0;i--){
upper.data[i+dim*i]=1/upper.data[i+i*dim];
factor=-1*upper.data[i+dim*i]*upper.data[i+1+i*dim];
for(int j=i+1;j<dim;j++){
upper.data[j+i*dim]=factor*upper.data[j+(i+1)*dim];
}
}
print_square_matrix(square_matrix_multiplication(inverse,lower));
print_square_matrix(upper);
print_square_matrix(inverse);
}
int main(){
Square_Matrix newMatrix={4,calloc(16,sizeof(double))};
Square_Matrix index = {4,calloc(16,sizeof(double))};
for(int i=0;i<4;i++){
index.data[i+4*i]=1;
}
n_vector vector={4,calloc(4,sizeof(double))};
memcpy(newMatrix.data, (double[]){ 2,-1, 0, 0,
-1, 2,-1, 0,
0,-1, 2,-1,
0, 0, -1, 2},16 * sizeof(double));
memcpy(vector.data, (double[]){-5, 1, 4, 1},4*sizeof(double));
tridigonal_invert(newMatrix);
//index=square_matrix_multiplication(newMatrix,index);
//print_square_matrix(index);
free(newMatrix.data);
free(vector.data);
free(index.data);
//print_square_matrix(index);
//print_square_matrix(square_matrix_multiplication(newMatrix,index));
/*vector = tridiagonal_solve(newMatrix,vector);
print_n_vector(vector);*/
}
这一行在tridigonal_invert
upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
在 i == 3
时超出两个内存区域的范围,调用未定义的行为。 dim == 4
,upper
和 matrix
都有 space 保留 16 double
秒(有效索引 [0, 15]),但是当 i == 3
在此循环中,i+1+i*dim == 16
,超出范围 1.
也可能存在其他越界情况,建议在 valgrind 中 运行 尝试识别它们。