代码之家  ›  专栏  ›  技术社区  ›  nikhilbalwani

为什么在传递给函数后访问指针会导致分段错误?

  •  -2
  • nikhilbalwani  · 技术社区  · 6 年前

    我想写一个二维快速傅里叶变换的C程序。其思想是通过预先分配的内存传递结构指针,其中函数将修改这些内存地址。

    复数是一种支持复数运算的结构,如加、减、乘、除、幂、复指数。我放置printf(“Hello\n”);语句的位置就是代码中发生分段错误的地方。谢谢你的期待。

    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    typedef struct complex_num_struct {
        double real;
        double imag;
    } complex_num;
    
    complex_num add(complex_num num1, complex_num num2);
    complex_num subtract(complex_num num1, complex_num num2);
    complex_num multiply(complex_num num1, complex_num num2);
    complex_num divide(complex_num num1, complex_num num2);
    complex_num power(complex_num num, double n);
    complex_num complex_exp(double theta);
    double magnitude(complex_num num);
    void display_complex_matrix(complex_num** matrix, int height, int width);
    void fft2(complex_num** input, complex_num** output, int height, int width);
    void fft_driver(complex_num input[], complex_num output[], int n, int step);
    void fft(complex_num input[], complex_num output[], int n);
    void display_complex_vec(complex_num * vec, int n);
    complex_num conjugate(complex_num num);
    complex_num ** matrix;
    complex_num ** temp;
    
    void main() {
    
        complex_num one;
        one.real = 1;
        one.imag = 0;
    
        complex_num height, width;
    
        height.real = 4;
        width.real = 4;
        height.imag = 0;
        width.imag = 0;
    
        complex_num zero;
        zero.real = 0;
        zero.imag = 0;
    
        complex_num input1[] = {one, one, one, one};
        complex_num input2[] = {one, one, one, one};
        complex_num input3[] = {zero, zero, zero, zero};
        complex_num input4[] = {zero, zero, zero, zero};
    
        complex_num* input[] = {input1, input2, input3, input4};
        complex_num* output[] = {input1, input2, input3, input4};
        complex_num* conj[] = {input1, input2, input3, input4};
    
        fft2(input, output, 4, 4);
        display_complex_matrix(output, 4, 4);
    
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                conj[i][j] = conjugate(output[i][j]);
            }
        }
    
        fft2(conj, output, 4, 4);
    
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                output[i][j] = conjugate(divide(conj[i][j], (multiply(height, width))));
            }
        }
    
        display_complex_matrix(output, 4, 4);
    }
    void fft2(complex_num** input, complex_num** output, int height, int width) {
    
        matrix = (complex_num **) malloc(height * sizeof(complex_num*));
        temp = (complex_num **) malloc(width * sizeof(complex_num*));
    
        for (int i = 0; i < height; ++i) {
            fft(input[i], temp[i], width);
        }
    
        for (int i = 0; i < height; ++i) {
    
            //matrix[i] = (complex_num*) malloc(height * sizeof(complex_num));
    
            for (int j = 0; j < width; ++j) {
                //matrix[i][j] = temp[j][i];
                printf("%lf", temp[j][i].real);
    
            }
        }
    
        for (int i = 0; i < height; ++i) {
            fft(matrix[i], temp[i], width);
        }
    
        for (int i = 0; i < height; ++i) {
            for (int j = 0; j < width; ++j) {
                output[i][j] = temp[j][i];
            }
        }
    }
    
    void display_complex_vec(complex_num vec[], int n) {
    
        printf("[");
    
        for (int i = 0; i < n; ++i) {
            printf("(%g, %g), ", vec[i].real, vec[i].imag);
        }
    
        printf("]\n");
    }
    
    void display_complex_matrix(complex_num** matrix, int height, int width) {
    
    
        for (int i = 0; i < height; ++i) {
            printf("[");
    
            for (int j = 0; j < width; ++j) {
                printf("(%g, %g), ", matrix[i][j].real, matrix[i][j].imag);
            }
    
            printf("]\n");
        }
    }
    
    void fft_driver(complex_num input[], complex_num output[], int n, int step) {
        complex_num diff, cexp;
    
        if (step < n) {
    
            fft_driver(output, input, n, step * 2);
            fft_driver(output + step, input + step, n, step * 2);
    
            for (int i = 0; i < n; i += 2 * step) {
                cexp = complex_exp(-M_PI * (double) i / (double) n);
    
                diff = multiply(complex_exp(-M_PI * (double) i / (double) n), output[i + step]);
    
                input[i / 2] = add(output[i], diff);
                input[(i + n) / 2] = subtract(output[i], diff);
                //printf("(%g, %g) * (%g, %g)\n", input[i / 2].real, input[i / 2].imag, input[(i + n) / 2].real, input[(i + n) / 2].imag);
            }
        }
    }
    
    void fft(complex_num* input, complex_num* output, int n) {
    
        complex_num* dummy = (complex_num *)malloc(n * sizeof(complex_num));
        complex_num* inp = (complex_num *)malloc(n * sizeof(complex_num));
    
        for (int i = 0; i < n; ++i) {
            dummy[i].real = 0;
            dummy[i].imag = 0;
            inp[i].real = 0;
            inp[i].imag = 0;
        }
    
        printf("%lf", inp[1].real);
        for (int i = 0; i < n; ++i) {
            dummy[i] = input[i];
            inp[i] = input[i];
        }
    
        fft_driver(inp, dummy, n, 1);
    
        printf("Hello\n");
    
        for (int i = 0; i < n; ++i) {
            output[i] = inp[i];
        }
    }
    
    complex_num complex_exp(double theta) {
        complex_num result;
        result.real = cos(theta);
        result.imag = sin(theta);
    
        return result;
    }
    
    double magnitude(complex_num num) {
        return sqrt(pow(num.real, 2) + pow(num.imag, 2));
    }
    
    complex_num add(complex_num num1, complex_num num2) {
        complex_num result;
        result.real = num1.real + num2.real;
        result.imag = num1.imag + num2.imag;
    
        return result;
    }
    
    complex_num conjugate(complex_num num) {
        complex_num result;
        result.real = num.real;
        result.imag = -num.imag;
    
        return result;
    }
    
    complex_num subtract(complex_num num1, complex_num num2) {
        complex_num result;
        result.real = num1.real - num2.real;
        result.imag = num1.imag - num2.imag;
    
        return result;
    }
    
    complex_num multiply(complex_num num1, complex_num num2) {
        complex_num result;
        result.real = num1.real * num2.real - num1.imag * num2.imag;
        result.imag = num1.real * num2.imag + num1.imag * num2.real;
    
        return result;
    }
    
    complex_num divide(complex_num num1, complex_num num2) {
        complex_num result;
    
        double magnitude_square = pow(num2.real, 2) + pow(num2.imag, 2);
        num2.imag = -num2.imag;
    
        result = multiply(num1, num2);
        result.real = result.real / magnitude_square;
        result.imag = result.imag / magnitude_square;
    
        return result;
    }
    
    complex_num power(complex_num num, double n) {
        complex_num result;
    
        double magnitude = sqrt(pow(num.real, 2) + pow(num.imag, 2));
    
        result.real = pow(magnitude, n) * cos(n * atan(num.imag / num.real));
        result.imag = pow(magnitude, n) * sin(n * atan(num.imag / num.real));
    
        return result;
    }
    

    0.000000Hello
    Segmentation fault (core dumped)
    

    void fft(complex_num* input, complex_num* output, int n) {
    
        complex_num* dummy = (complex_num *)malloc(n * sizeof(complex_num));
        complex_num* inp = (complex_num *)malloc(n * sizeof(complex_num));
    
        for (int i = 0; i < n; ++i) {
            dummy[i].real = 0;
            dummy[i].imag = 0;
            inp[i].real = 0;
            inp[i].imag = 0;
        }
    
        printf("%lf", inp[1].real);
        for (int i = 0; i < n; ++i) {
            dummy[i] = input[i];
            inp[i] = input[i];
        }
    
        fft_driver(inp, dummy, n, 1);
    
        printf("Hello\n");
    
        for (int i = 0; i < n; ++i) {
            output[i] = inp[i];
        }
    }
    

    所需输出应为下图:-

    0.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    4.0000004.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    [(8, 0), (0, 0), (0, 0), (0, 0), ]
    [(4, -4), (0, 0), (0, 0), (0, 0), ]
    [(0, 0), (0, 0), (0, 0), (0, 0), ]
    [(4, 4), (0, 0), (0, 0), (0, 0), ]
    0.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    4.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000004.0000000.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    [(1, 1), (1, 1), (1, 1), (1, 1), ]
    [(0.0625, -0.0625), (0.0625, -0.0625), (0.0625, -0.0625), (0.0625, -0.0625), ]
    [(0.0625, -0.0625), (0.0625, -0.0625), (0.0625, -0.0625), (0.0625, -0.0625), ]
    [(0.0625, -0.0625), (0.0625, -0.0625), (0.0625, -0.0625), (0.0625, -0.0625), ]
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   nikhilbalwani    6 年前

    您有一个分段错误,因为您正在写入中的未初始化地址 void fft(complex_num* input, complex_num* output, int n)

    output[i] = inp[i];
    

    输出 来自 排队

    fft(input[i], temp[i], width);
    

    哪里 临时雇员 由设置

    temp = (complex_num **) malloc(width * sizeof(complex_num*));
    

    temp[i] 未初始化

    也许 fft(input[i], temp[i], width); 应该是 fft(input[i], &temp[i], width); 虽然 快速傅里叶变换 成为:

    void fft(complex_num* input, complex_num** output, int n) {
    
      complex_num* dummy = (complex_num *)malloc(n * sizeof(complex_num));
      complex_num* inp = (complex_num *)malloc(n * sizeof(complex_num));
    
      for (int i = 0; i < n; ++i) {
        dummy[i].real = 0;
        dummy[i].imag = 0;
        inp[i].real = 0;
        inp[i].imag = 0;
      }
    
      printf("%lf", inp[1].real);
      for (int i = 0; i < n; ++i) {
        dummy[i] = input[i];
        inp[i] = input[i];
      }
    
      fft_driver(inp, dummy, n, 1);
    
      printf("Hello\n");
    
      *output = inp;
    }
    

    总之还有一个问题 fft2型 在通话中:

    fft(matrix[i], &temp[i], width);
    

    因为初始化 matrix[i] 矩阵[i] 快速傅里叶变换 您正在访问这些行中的未知地址

    dummy[i] = input[i];
    inp[i] = input[i];
    

    线 //matrix[i] = (complex_num*) malloc(height * sizeof(complex_num));

    matrix[i] = (complex_num*) malloc(width * sizeof(complex_num));
    

    matrix[i][j] = temp[j][i]; 不能在注释中

    /tmp % ./a.out
    0.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    4.0000004.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    [(8, 0), (0, 0), (0, 0), (0, 0), ]
    [(4, -4), (0, 0), (0, 0), (0, 0), ]
    [(0, 0), (0, 0), (0, 0), (0, 0), ]
    [(4, 4), (0, 0), (0, 0), (0, 0), ]
    0.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    8.0000004.0000000.0000004.0000008.0000004.0000000.0000004.0000008.0000004.0000000.0000004.0000008.0000004.0000000.0000004.0000000.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    [(1, -0), (1, -0), (1, -0), (1, -0), ]
    [(1, -2.8606e-18), (1, -2.8606e-18), (1, -2.8606e-18), (1, -2.8606e-18), ]
    [(0, 0), (0, -0), (0, -0), (0, -0), ]
    [(0, 2.8606e-18), (0, 2.8606e-18), (0, 2.8606e-18), (0, 2.8606e-18), ]
    

    我不知道这是否是预期产出,但至少 瓦尔格林 不检测任何非法内存访问或未初始化的值。

    如果存在内存泄漏,请执行以下操作:

    在里面 代替

    for (int i = 0; i < height; ++i) {
      fft(matrix[i], &temp[i], width);
    }
    

    for (int i = 0; i < height; ++i) {
      free(temp[i]);
      fft(matrix[i], &temp[i], width);
      free(matrix[i]);
    }
    
    free(matrix);
    

    最后加上

    for (int i = 0; i < height; ++i)
      free(temp[i]);
    free(temp);
    

    添加 free(dummy); 在结束之前

    这些更改可消除所有内存泄漏:

    /tmp % valgrind --leak-check=full ./a.out
    ==12924== Memcheck, a memory error detector
    ==12924== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
    ==12924== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
    ==12924== Command: ./a.out
    ==12924== 
    0.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    4.0000004.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    [(8, 0), (0, 0), (0, 0), (0, 0), ]
    [(4, -4), (0, 0), (0, 0), (0, 0), ]
    [(0, 0), (0, 0), (0, 0), (0, 0), ]
    [(4, 4), (0, 0), (0, 0), (0, 0), ]
    0.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    8.0000004.0000000.0000004.0000008.0000004.0000000.0000004.0000008.0000004.0000000.0000004.0000008.0000004.0000000.0000004.0000000.000000Hello
    0.000000Hello
    0.000000Hello
    0.000000Hello
    [(1, -0), (1, -0), (1, -0), (1, -0), ]
    [(1, -2.8606e-18), (1, -2.8606e-18), (1, -2.8606e-18), (1, -2.8606e-18), ]
    [(0, 0), (0, -0), (0, -0), (0, -0), ]
    [(0, 2.8606e-18), (0, 2.8606e-18), (0, 2.8606e-18), (0, 2.8606e-18), ]
    ==12924== 
    ==12924== HEAP SUMMARY:
    ==12924==     in use at exit: 0 bytes in 0 blocks
    ==12924==   total heap usage: 44 allocs, 44 frees, 2,688 bytes allocated
    ==12924== 
    ==12924== All heap blocks were freed -- no leaks are possible
    ==12924== 
    ==12924== For counts of detected and suppressed errors, rerun with: -v
    ==12924== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
    

    int main() 而不是 void main()


    如果我把所有代码都放在帮助您,因为有很多更改:

    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    
    #ifndef M_PI
    #define M_PI 3.1415927
    #endif
    
    typedef struct complex_num_struct {
        double real;
        double imag;
    } complex_num;
    
    complex_num add(complex_num num1, complex_num num2);
    complex_num subtract(complex_num num1, complex_num num2);
    complex_num multiply(complex_num num1, complex_num num2);
    complex_num divide(complex_num num1, complex_num num2);
    complex_num power(complex_num num, double n);
    complex_num complex_exp(double theta);
    double magnitude(complex_num num);
    void display_complex_matrix(complex_num** matrix, int height, int width);
    void fft2(complex_num** input, complex_num** output, int height, int width);
    void fft_driver(complex_num input[], complex_num output[], int n, int step);
    void fft(complex_num input[], complex_num * output[], int n);
    void display_complex_vec(complex_num * vec, int n);
    complex_num conjugate(complex_num num);
    complex_num ** matrix;
    complex_num ** temp;
    
    int main() {
    
        complex_num one;
        one.real = 1;
        one.imag = 0;
    
        complex_num height, width;
    
        height.real = 4;
        width.real = 4;
        height.imag = 0;
        width.imag = 0;
    
        complex_num zero;
        zero.real = 0;
        zero.imag = 0;
    
        complex_num input1[] = {one, one, one, one};
        complex_num input2[] = {one, one, one, one};
        complex_num input3[] = {zero, zero, zero, zero};
        complex_num input4[] = {zero, zero, zero, zero};
    
        complex_num* input[] = {input1, input2, input3, input4};
        complex_num* output[] = {input1, input2, input3, input4};
        complex_num* conj[] = {input1, input2, input3, input4};
    
        fft2(input, output, 4, 4);
        display_complex_matrix(output, 4, 4);
    
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                conj[i][j] = conjugate(output[i][j]);
            }
        }
    
        fft2(conj, output, 4, 4);
    
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                output[i][j] = conjugate(divide(conj[i][j], (multiply(height, width))));
            }
        }
    
        display_complex_matrix(output, 4, 4);
    }
    void fft2(complex_num** input, complex_num** output, int height, int width) {
    
        matrix = (complex_num **) malloc(height * sizeof(complex_num*));
        temp = (complex_num **) malloc(width * sizeof(complex_num*));
    
        for (int i = 0; i < height; ++i) {
            fft(input[i], &temp[i], width);
        }
    
        for (int i = 0; i < height; ++i) {
    
            matrix[i] = (complex_num*) malloc(width * sizeof(complex_num));
    
            for (int j = 0; j < width; ++j) {
                matrix[i][j] = temp[j][i];
                printf("%lf", temp[j][i].real);
    
            }
        }
    
        for (int i = 0; i < height; ++i) {
            free(temp[i]);
            fft(matrix[i], &temp[i], width);
            free(matrix[i]);
        }
    
        free(matrix);
    
        for (int i = 0; i < height; ++i) {
            for (int j = 0; j < width; ++j) {
                output[i][j] = temp[j][i];
            }
        }
        for (int i = 0; i < height; ++i)
          free(temp[i]);
        free(temp);
    }
    
    void display_complex_vec(complex_num vec[], int n) {
    
        printf("[");
    
        for (int i = 0; i < n; ++i) {
            printf("(%g, %g), ", vec[i].real, vec[i].imag);
        }
    
        printf("]\n");
    }
    
    void display_complex_matrix(complex_num** matrix, int height, int width) {
    
    
        for (int i = 0; i < height; ++i) {
            printf("[");
    
            for (int j = 0; j < width; ++j) {
                printf("(%g, %g), ", matrix[i][j].real, matrix[i][j].imag);
            }
    
            printf("]\n");
        }
    }
    
    void fft_driver(complex_num input[], complex_num output[], int n, int step) {
        complex_num diff, cexp;
    
        if (step < n) {
    
            fft_driver(output, input, n, step * 2);
            fft_driver(output + step, input + step, n, step * 2);
    
            for (int i = 0; i < n; i += 2 * step) {
                cexp = complex_exp(-M_PI * (double) i / (double) n);
    
                diff = multiply(complex_exp(-M_PI * (double) i / (double) n), output[i + step]);
    
                input[i / 2] = add(output[i], diff);
                input[(i + n) / 2] = subtract(output[i], diff);
                //printf("(%g, %g) * (%g, %g)\n", input[i / 2].real, input[i / 2].imag, input[(i + n) / 2].real, input[(i + n) / 2].imag);
            }
        }
    }
    
    void fft(complex_num* input, complex_num** output, int n) {
    
      complex_num* dummy = (complex_num *)malloc(n * sizeof(complex_num));
      complex_num* inp = (complex_num *)malloc(n * sizeof(complex_num));
    
      for (int i = 0; i < n; ++i) {
        dummy[i].real = 0;
        dummy[i].imag = 0;
        inp[i].real = 0;
        inp[i].imag = 0;
      }
    
      printf("%lf", inp[1].real);
      for (int i = 0; i < n; ++i) {
        dummy[i] = input[i];
        inp[i] = input[i];
      }
    
      fft_driver(inp, dummy, n, 1);
    
      free(dummy);
      printf("Hello\n");
    
      *output = inp;
    }
    
    complex_num complex_exp(double theta) {
        complex_num result;
        result.real = cos(theta);
        result.imag = sin(theta);
    
        return result;
    }
    
    double magnitude(complex_num num) {
        return sqrt(pow(num.real, 2) + pow(num.imag, 2));
    }
    
    complex_num add(complex_num num1, complex_num num2) {
        complex_num result;
        result.real = num1.real + num2.real;
        result.imag = num1.imag + num2.imag;
    
        return result;
    }
    
    complex_num conjugate(complex_num num) {
        complex_num result;
        result.real = num.real;
        result.imag = -num.imag;
    
        return result;
    }
    
    complex_num subtract(complex_num num1, complex_num num2) {
        complex_num result;
        result.real = num1.real - num2.real;
        result.imag = num1.imag - num2.imag;
    
        return result;
    }
    
    complex_num multiply(complex_num num1, complex_num num2) {
        complex_num result;
        result.real = num1.real * num2.real - num1.imag * num2.imag;
        result.imag = num1.real * num2.imag + num1.imag * num2.real;
    
        return result;
    }
    
    complex_num divide(complex_num num1, complex_num num2) {
        complex_num result;
    
        double magnitude_square = pow(num2.real, 2) + pow(num2.imag, 2);
        num2.imag = -num2.imag;
    
        result = multiply(num1, num2);
        result.real = result.real / magnitude_square;
        result.imag = result.imag / magnitude_square;
    
        return result;
    }
    
    complex_num power(complex_num num, double n) {
        complex_num result;
    
        double magnitude = sqrt(pow(num.real, 2) + pow(num.imag, 2));
    
        result.real = pow(magnitude, n) * cos(n * atan(num.imag / num.real));
        result.imag = pow(magnitude, n) * sin(n * atan(num.imag / num.real));
    
        return result;
    }