C:如果调用顺序改变,使用结构的嵌套函数会破坏程序

Posted

技术标签:

【中文标题】C:如果调用顺序改变,使用结构的嵌套函数会破坏程序【英文标题】:C: Nested functions using structs break the program if order of call is changed 【发布时间】:2021-12-24 03:38:18 【问题描述】:

我在编程练习中遇到了一个问题,由于程序正在编译,所以我找不到问题的根源 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);*/


【问题讨论】:

您的完整代码无法编译。 已编辑,现在应该可以使用了! 具体问题是什么..它崩溃了?给你意想不到的输出? 粉碎而没有任何输出 欢迎。您应该阅读How to Ask 并选择tour。 【参考方案1】:

tridigonal_invert中的这一行

upper.data[i+1+i*dim]=matrix.data[i+1+i*dim];
i == 3 调用未定义的行为时,

超出两个内存区域的范围。 dim == 4uppermatrix 都保留了 16 个 doubles 的空间(有效索引为 [0, 15]),但当 i == 3 在此循环中时,i+1+i*dim == 16 超出 1 .

可能还有其他越界事件,建议在 valgrind 中运行以尝试识别它们。

【讨论】:

非常感谢,我会尝试搜索更多越界索引。

以上是关于C:如果调用顺序改变,使用结构的嵌套函数会破坏程序的主要内容,如果未能解决你的问题,请参考以下文章

C语言中函数怎么自己调用自己

C语言函数归纳

c语言的流程图怎么画?

函数参数的破坏顺序是啥?

C语言博客作业--函数嵌套调用

装饰器及模块