【问题标题】:dynamically allocated matrix gives seg fault when printed动态分配的矩阵在打印时会出现段错误
【发布时间】:2018-05-01 15:17:01
【问题描述】:

这段代码通过一系列函数调用来分配一个矩阵,但是当我打印它时,它返回了一个分段错误错误。

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

void mat_init(int** matx);
void pp_init(int** matx);
void p_init(int** matx);
void mat_fill(int** matx);
void mat_print(int** matx);

int main(void)
{
    srand((unsigned)time(NULL));
    int** matrix;
    mat_init(matrix);
    mat_print(matrix);
    return 0;
}

void mat_init(int** matx)
{
    pp_init(matx);
}

void pp_init(int** matx)
{

    matx=malloc(4*sizeof(int*));
    p_init(matx);
}

void p_init(int** matx)
{
    for(int i=0;i<4;i++)
    {
        *(matx+i)=malloc(4*sizeof(int));
    }
    mat_fill(matx);
}

void mat_fill(int** matx)
{
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            *(*(matx+i)+j)=rand()%5;
        }
    }
    //mat_print(matx);
}

void mat_print(int** matx)
{
    printf("The matrix is:\n");
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%1i|",*(*(matx+i)+j));
        }
        puts("");
    }
    puts("");
}

请注意,仅当我使用 mat_print() int 打印矩阵时才会发生这种情况,如果我在函数 mat_fill() 中使用它,它可以正常工作,表明它已正确初始化。 有什么问题?

【问题讨论】:

  • 为什么?矩阵的地址不是我已经传递给函数了吗?为什么我必须给指向第一个函数的指针的指针?
  • c 中的所有内容都是按值传递的。当您将matx 传递给函数时,会生成一个本地副本,就像您传递int 一样。您对该本地副本所做的任何操作都仅限于其本地范围。如果您希望在本地范围之外看到本地操作,则必须返回该值(或者在此处的指针的情况下,您可以取消引用指针并修改它指向的内容)。但是matx 在这里传递时并没有指向任何东西。如果你通过&amp;matx,那么它会指向一些东西,但是在我的经验中处理3星指针并不是很常见。
  • 所以它不起作用,因为当我将指针传递给函数时,指向指针的矩阵指针未初始化......如果我做了 matrix=malloc(4*sizeof(int*));基本上,去掉 pp_init 就可以了,对吧?
  • 可能。测试一下。

标签: c matrix malloc


【解决方案1】:

基本上你正在做的是:

void foo(int a);
{
  a = 6;
}

int main()
{
  int a = 3;
  foo(a);
  printf("a = %d\n", a);  // expecting this to print 6

  return 0;
}

C 中的所有内容都是按值传递的,这意味着任何时候将参数传递给函数,都会在该函数中创建其本地副本,并且其范围仅存在于该函数中;指针也不例外。如果我有此代码:

void foo (int* ap2)
{
  // there are now 2 pointers in memory that point to the same thing (main's a), namely
  // ap2 on this stack frame and ap1 in the previous stack frame.
  *ap2 = 6;
  // ap2 is local to this function, but it _points_ to the same thing as
  // ap1, so when we dereference it, changes to _what it points to_ are seen
  // outside of this function. But once we return from this function, ap2
  // ceases to exist
}

int main()
{
  int a = 3;
  int* ap1 = &a;
  foo(ap1);
  printf("a = %d\n", a);  // now this prints 6

  return 0;
}

如果您想在函数中操作mainmatx,那么您需要传递一个指向它的指针并在该函数中取消引用它以修改它指向的内容 .

void foo (int*** matxp)
{
  // matxp now points to matx in main
  // dereference it here
  *matxp = malloc(4 * sizeof(int*));
}
int main()
{
  int** matx;
  foo(&matx);  // pass the address of matx here, which is an int*** type

  ....

  // don't forget to clean up everything
  return 0;
}

但正如我在 cmets 中所说,我很少/从未见过 3 星指针。相反,您可以只返回值

int** foo()
{
  matxp = malloc(4 * sizeof(int*));
  return matxp;  // this will return NULL if malloc failed
}

int main()
{
  int** matx = foo();

  ....
  // do work, cleanup
  return 0;
}

【讨论】:

    【解决方案2】:

    你需要这样做:

    int** mat_init(int** matx);
    int** pp_init(int** matx);
    
    int main(void)
    {
        matrix=mat_init(matrix);
    }
    
    int** mat_init(int** matx)
    {
        return pp_init(matx);
    }
    
    int** pp_init(int** matx)
    {
        matx=malloc(4*sizeof(int*));
        p_init(matx);
        return matx;
    }
    

    我省略了一些我没有更改的行。另一种选择是:

    void mat_init(int*** matx);
    void pp_init(int*** matx);
    
    int main(void)
    {
        mat_init(&matrix);
    }
    
    void mat_init(int*** matx)
    {
        pp_init(matx);
    }
    
    void pp_init(int*** matx)
    {
        *matx=malloc(4*sizeof(int*));
        p_init(*matx);
    }
    

    另一件事:您在很多地方都使用了值4。那很危险。改为使用常量。

    #define MAT_SIZE 4
    
    void mat_fill(int** matx) {
        for(int i=0;i<MAT_SIZE;i++) {
            for(int j=0;j<MAT_SIZE;j++)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-08
      • 2013-04-05
      • 2019-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      相关资源
      最近更新 更多