繁体   English   中英

访问结构从指针返回的结构中的2D数组时出现分段错误

[英]Segmentation fault when accessing a 2D array in a structure whose pointer is returned from a function

我创建了一个具有两个成员( intint** )的结构,并将指向该结构的指针从一个函数返回到main() 可以在结构中访问int值。 但是,在main()当我尝试访问2D数组的元素时遇到了Segmentation错误:11。

#include<stdio.h>
#include<stdlib.h>

typedef struct Square {
    int value;
    int **array;
} Square;

Square * generate();

int main(int argc, char *argv[]){
    Square *sqrptr = generate();

    printf("%d\n", sqrptr -> value);
    /* It prints 1 */

    /* Print out the 2D array */
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3 ; j++){
            printf("%d ", *(*((sqrptr -> array) + i) + j));
        }
        printf("\n");
    }
    /* It gives segmentation fault */

    return 0;
}

Square * generate(){
    Square mySquare;
    mySquare.value = 1;
    mySquare.array = malloc(sizeof(int*) * 3);

    /* Initialize the 2D array */
    for (int i = 0; i < 3; i++){
        *(mySquare.array + i) = malloc(sizeof(int) * 3);
        for (int j = 0; j < 3; j++){
            *(*(mySquare.array + i) + j) = 0;
        }
    }

    /* Print out the 2D array */
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3l ; j++){
            printf("%d ", *(*(mySquare.array + i) + j));
        }
        printf("\n");
    }
    /* I can see the complete 2D array here */

    Square *sqrptr = &mySquare;

    return sqrptr;    
}

我尝试在main()生成Square ,并使用结构的一个指针访问我的2D数组。 它工作正常,所以我想我在使用其他函数返回的指针时会漏掉一些东西。 另一方面,我可以成功访问int value ,所以现在没有任何线索了。

有人可以解释这种细分错误的根本原因吗? 谢谢!

您正在返回一个指向局部变量( &mySquare )的指针。 函数返回时就是堆栈内存(局部变量所在的位置),因此结果指针指向无效的内存。 分配该结构,然后将指针返回到堆内存:

Square *my_square = malloc(sizeof *my_square);
//do stuff
return my_square;

或将指向堆栈变量的指针作为参数传递:

Square * generate(Square *my_square)
{
    //in case pointer wasn't provided, allocate
    if (my_square == NULL) {
        my_square = malloc(sizeof *my_square);
        if (!my_square)
            return NULL; // or exit or whatever
    }
    //initialize members. To initialize array to 3x3 zero matrix, you can use:
    for (int i=0;i<3;++i)
        my_square.array[i] = calloc(3, sizeof *my_square->array[i]);
    //or even, if you change array member to type int*:
    my_square.array = calloc(3*3, sizeof *my_square->array);
    //at the end:
    return my_square;
}

后者可以说是最灵活的解决方案:如果要在堆栈上工作,可以像下面这样调用函数:

Square my_stack_square;
generate(&my_stack_square);

如果需要使用堆内存,则可以使用:

Square *my_heap_square = generate(NULL);

正如乔纳森·莱夫勒(Jonathan Leffler)所指出的那样,对于像这样的小型结构,按价值回报并不会花费太多。 可以通过与返回任何其他类型相同的方式来实现在堆上获取结构:

Square generate( void )
{
    Square my_square;
    //initialize
    return my_square;
}
//call like so:
Square sq = generate();

这里的想法是,您将在generate函数中使用局部变量来创建一个新的正方形,初始化字段,然后返回它。 因为在C语言中,所有内容都是通过value传递 ,这实质上意味着函数会将生成函数中局部变量的值分配给调用方的作用域sq变量。 对于像这样的小型结构,这是完全可以的。

更重要的是,编译器要做的一件事是将这些函数优化为与我发布的第二个示例等效:本质上,您的函数将在调用者的堆栈存储器上创建一个新的Sqaure对象。 可能发生,但这并不是说会发生。 这取决于编译时使用的优​​化级别,以及要返回的结构的大小。

基本上,如果您想使代码保持与现在的状态接近,则最容易坚持使用第一个版本(返回堆指针)。

第二种方法更加灵活(因为它允许您使用堆栈和堆,具体取决于调用函数的方式)。

就目前而言,使用第三种方法非常好:编译器很可能会将代码优化为最有意义的代码。

尝试这个:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct Square {
    int value;
    int **array;
} Square;

Square * generate();

int main(int argc, char *argv[]){
    Square *sqrptr = generate();

    printf("%d\n", sqrptr -> value);
    /* It prints 1 */

    /* Print out the 2D array */
    int i,j;
    for (i = 0; i < 3; i++){
        for (j = 0; j < 3 ; j++){
            printf("%d ", *(*((sqrptr -> array) + i) + j));
        }
        printf("\n");
    }
    /* It gives segmentation fault */

    return 0;
}

Square * generate(){
    Square* mySquare = (Square*) malloc(sizeof(Square)); //c++ compiler
    //Square* mySquare = (void*) malloc(sizeof(Square)); //c compiler
    mySquare->value = 1;
    mySquare->array = malloc(sizeof(int*) * 3);

    /* Initialize the 2D array */
    int i,j;
    for (i = 0; i < 3; i++){
        *(mySquare->array + i) = malloc(sizeof(int) * 3);
        for (j = 0; j < 3; j++){
            *(*(mySquare->array + i) + j) = 0;
        }
    }

    /* Print out the 2D array */
    for (i = 0; i < 3; i++){
        for (j = 0; j < 3l ; j++){
            printf("%d ", *(*(mySquare->array + i) + j));
        }
        printf("\n");
    }
    /* I can see the complete 2D array here */
    return mySquare;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM