为什么在返回指向本地静态变量的指针时此程序会出现段错误?

时间:2021-07-30 16:49:05

This is related to an earlier question of mine. I tried expanding the code a little bit and to play around with different ways of returning pointers to local static variables, especially returning two-dimensional arrays. (This is seriously just to understand how pointers to arrays work and how they behave in function environments. It has not even the slightest intent of returning arrays the smart way using structs.) I wrote two functions both transpose matrices. The function transpose() only transposes 2x4-matrices and the function transpose_generic() is supposed to transpose matrices of arbitrary size. There is no real use to them. After I have declared and defined the functions I call them from int main(int argc, char *argv[]){}. The two matrices that have been transposed are supposed to be printed to stdout in a simple for-loop. And here is something I don't understand. Depending on whether I declare the matrices that are supposed to be transposed as global or local variables I get a segfault or "clean" exit. I can also prevent the compiled program from segfaulting by using a for loop after the for loop that prints the transposed matrices to stdout. But the for-loop needs to use a new index. I'm sure I'm missing something very basic but I cannot figure this out on my own. Even after extensive internet searching I'm still puzzled. So maybe someone can enlighten me. Here is the code:

这与我之前的一个问题有关。我尝试了一点点扩展代码,并尝试使用不同的方法返回指向本地静态变量的指针,尤其是返回二维数组。 (这只是为了理解数组的指针是如何工作的以及它们在函数环境中的行为方式。它甚至没有使用结构以智能方式返回数组的最轻微的意图。)我编写了两个转置矩阵的函数。函数transpose()仅转置2x4矩阵,函数transpose_generic()应该转置任意大小的矩阵。他们没有真正的用处。在我声明并定义了函数后,我从int main(int argc,char * argv []){}调用它们。已经转置的两个矩阵应该以简单的for循环打印到stdout。这是我不明白的事情。根据我是否声明应该转换为全局或局部变量的矩阵,我得到段错误或“干净”退出。我还可以通过在for循环之后使用for循环来阻止编译的程序进行segfaulting,该循环将转置的矩阵打印到stdout。但for循环需要使用新索引。我敢肯定我错过了一些非常基本的东西,但我无法自己解决这个问题。即使经过广泛的互联网搜索,我仍然感到困惑。所以也许有人可以启发我。这是代码:

Will segfault

#include <stdio.h>

int mat1[2][4] = {
    {9, 10, 11, 12},
    {13, 14, 15, 16}
};

int mat2[2][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8}
};

typedef matx[2];
matx *transpose(int matrix[][4]);

typedef maty[];
maty *transpose_generic(int nrow, int ncol, int matrix1[nrow][ncol], int matrix2[nrow][ncol]);

int main(int argc, char *argv[]) {

    /* This may need a little bit of clarification. Here we want to declare a
     * pointer to an array and we need the round brackets () for this. If we
     * were simply to write *mat_transpose[2] we would declare an array of
     * pointers since [] has higher precedence than *. */
    int (*mat_transpose)[2];

    int tmat[2][4];
    int i;
    int j;

    mat_transpose = transpose(mat1);
    transpose_generic(2, 4, mat2, tmat);

    for (j = 0; j < 2; j++) {
        for (i = 0; i < 4; i++) {
            printf("mat_transpose[%d][%d] = %d\n", i, j, mat_transpose[i][j]);
            printf("tmat[%d][%d] = %d\n", i, j, tmat[i][j]);
        }
    }
    return 0;
}

matx *transpose(int matrix[][4]) {
    static int mat[4][2];
    int i;
    int j;

    printf("Transpose a 2x4 matrix\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 4; j++) {
            mat[j][i] = matrix[i][j];
        }
    }
    return mat;
}

maty *transpose_generic(int nrow, int ncol,
                        int matrix1[nrow][ncol],
                        int matrix2[nrow][ncol]) {
    int i;
    int j;

    printf("Transpose a matrix\n\n");
    for (i = 0; i < nrow; i++) {
        for (j = 0; j < ncol; j++) {
            matrix2[j][i] = matrix1[i][j];
        }
    }
    return matrix2;
}

Will exit clean

#include <stdio.h>

typedef matx[2];
matx *transpose(int matrix[][4]);

typedef maty[];
maty *transpose_generic(int nrow, int ncol, int matrix1[nrow][ncol], int matrix2[nrow][ncol]);

int main(int argc, char *argv[]) {

    int mat1[2][4] = {
        {9, 10, 11, 12},
        {13, 14, 15, 16}
    };

    int mat2[2][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8}
    };


    /* This may need a little bit of clarification. Here we want to declare a
     * pointer to an array and we need the round brackets () for this. If we
     * were simply to write *mat_transpose[2] we would declare an array of
     * pointers since [] has higher precedence than *. */
    int (*mat_transpose)[2];

    int tmat[2][4];
    int i;
    int j;

    mat_transpose = transpose(mat1);
    transpose_generic(2, 4, mat2, tmat);

    for (j = 0; j < 2; j++) {
        for (i = 0; i < 4; i++) {
            printf("mat_transpose[%d][%d] = %d\n", i, j, mat_transpose[i][j]);
            printf("tmat[%d][%d] = %d\n", i, j, tmat[i][j]);
        }
    }
    return 0;
}

matx *transpose(int matrix[][4]) {
    static int mat[4][2];
    int i;
    int j;

    printf("Transpose a 2x4 matrix\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 4; j++) {
            mat[j][i] = matrix[i][j];
        }
    }
    return mat;
}

maty *transpose_generic(int nrow, int ncol,
        int matrix1[nrow][ncol],
        int matrix2[nrow][ncol]) {
    int i;
    int j;

    printf("Transpose a matrix\n\n");
    for (i = 0; i < nrow; i++) {
        for (j = 0; j < ncol; j++) {
            matrix2[j][i] = matrix1[i][j];
        }
    }
    return matrix2;
}

Will exit clean

#include <stdio.h>

int mat1[2][4] = {
    {9, 10, 11, 12},
    {13, 14, 15, 16}
};

int mat2[2][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8}
};

typedef matx[2];
matx *transpose(int matrix[][4]);

typedef maty[];
maty *transpose_generic(int nrow, int ncol, int matrix1[nrow][ncol], int matrix2[nrow][ncol]);

int main(int argc, char *argv[]) {

    /* This may need a little bit of clarification. Here we want to declare a
     * pointer to an array and we need the round brackets () for this. If we
     * were simply to write *mat_transpose[2] we would declare an array of
     * pointers since [] has higher precedence than *. */
    int (*mat_transpose)[2];

    int tmat[2][4];
    int i;
    int j;
    int k;

    mat_transpose = transpose(mat1);
    transpose_generic(2, 4, mat2, tmat);

    for (j = 0; j < 2; j++) {
        for (i = 0; i < 4; i++) {
            printf("mat_transpose[%d][%d] = %d\n", i, j, mat_transpose[i][j]);
            printf("tmat[%d][%d] = %d\n", i, j, tmat[i][j]);
        }
    }
    for (k = 0; k < 1; k++) {
        printf("H");
    }
    return 0;
}

matx *transpose(int matrix[][4]) {
    static int mat[4][2];
    int i;
    int j;

    printf("Transpose a 2x4 matrix\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 4; j++) {
            mat[j][i] = matrix[i][j];
        }
    }
    return mat;
}

maty *transpose_generic(int nrow, int ncol,
        int matrix1[nrow][ncol],
        int matrix2[nrow][ncol]) {
    int i;
    int j;

    printf("Transpose a matrix\n\n");
    for (i = 0; i < nrow; i++) {
        for (j = 0; j < ncol; j++) {
            matrix2[j][i] = matrix1[i][j];
        }
    }
    return matrix2;
}

1 个解决方案

#1


5  

In this line,

在这一行中,

        printf("tmat[%d][%d] = %d\n", i, j, tmat[i][j]);

When i>1 your code causes undefined behaviour since you tmat is declared as int tmat[2][4];.

当i> 1时,您的代码会导致未定义的行为,因为您将tmat声明为int tmat [2] [4] ;.

The same problem exists in all three code snippets and you just happen to get segfault only for the first one. This is not at all related to whether you return a a pointer to a function scoped static variable.

在所有三个代码片段中都存在同样的问题,而您恰好只为第一个代码段获得了段错误。这与您是否返回指向函数范围的静态变量的指针完全无关。

#1


5  

In this line,

在这一行中,

        printf("tmat[%d][%d] = %d\n", i, j, tmat[i][j]);

When i>1 your code causes undefined behaviour since you tmat is declared as int tmat[2][4];.

当i> 1时,您的代码会导致未定义的行为,因为您将tmat声明为int tmat [2] [4] ;.

The same problem exists in all three code snippets and you just happen to get segfault only for the first one. This is not at all related to whether you return a a pointer to a function scoped static variable.

在所有三个代码片段中都存在同样的问题,而您恰好只为第一个代码段获得了段错误。这与您是否返回指向函数范围的静态变量的指针完全无关。