【问题标题】:Segmentation faul while accessing 2d array?访问二维数组时出现分段错误?
【发布时间】:2014-09-13 03:22:21
【问题描述】:
#include <stdio.h>
#include <conio.h>

#define     GRID_X              30
#define     GRID_Y              20

unsigned char board[GRID_Y][GRID_X];

void draw_board( unsigned char ** );
void print_board( unsigned char ** );

int main()
{
    draw_board( board );
    getch();
    return 0;
}

void draw_board( unsigned char **board )
{

    unsigned int  r_itr = 0,
                  c_itr = 0;

    if( NULL == board )
    {
        printf( "cannot create board..!!" );
        exit(0);
    }

    r_itr = 0;

    for( c_itr = 0; c_itr < GRID_X; ++c_itr )
    {
        board[ r_itr ][ c_itr ] = '+'; /* <- crashing here  */
        board[ r_itr + ( GRID_Y-1 ) ][ c_itr ] = '+';
    }

    c_itr = 0;

    for( r_itr = 0; r_itr < GRID_Y; ++r_itr )
    {
        board[r_itr][c_itr] = '+';
        board[ r_itr ][ c_itr + GRID_X-1 ] = '+';
    }

    print_board( board );
 }

void print_board( unsigned char **board )
{
    int r = 0,
        c = 0;

    for( r = 0; r < GRID_Y; ++r )
    {
        for( c = 0; c < GRID_X; ++c )
        {
            printf( "%c", board[r][c] );
        }

        printf("\n");
    }
}

上面的代码在我通过评论提到的点崩溃(在此处崩溃)。 我做了所有可能的边界检查(根据我的理解),我仍然无法检测到崩溃的原因? 我使用了 GNU GCC 编译器和代码块 IDE。请帮忙?

【问题讨论】:

  • 你的函数参数的数据类型不对。 board 不是 unsigned char **;它是一个数组数组。它们不是同义词。
  • board 是全局变量时,为什么要将它作为参数传递给所有函数?
  • 我知道它很奇怪,但它实际上不是一个全球性的,我让它以一种简单的方式表达我的疑问。
  • 很多 C 初学者认为数组在传递时会衰减为指针,但它只衰减一次,因此二维数组不会衰减为指向指针的指针。

标签: c


【解决方案1】:

你应该使用:

void draw_board( unsigned char board[][GRID_X] )

void draw_board( unsigned char (*board)[GRID_X] )

更新

为什么问题中定义的函数draw_board 会导致问题?

假设你有

char b[2][3] = {{0}, {0}};

数组的内存布局为:

<--- b[0]     --->|<--- b[1]     --->

a1    a2    a3    a4    a5    a6
+-----+-----+-----+-----+-----+-----+
| 0   | 0   | 0   | 0   | 0   | 0   |
+-----+-----+-----+-----+-----+-----+

其中a1 ... a6 是地址。

当你将b传递给函数时,它会衰减为一个指针,传递给函数的值是a1

假设您有一个函数foo 声明为:

void foo(char** b);

当您将b 传递给foo 时,foob 的值是a1

b[0] = *b = *a1

保存在地址a1 的数据现在被视为char*。如果指针大小为4字节,

b[0] = 0;

如果您取消引用 b[0],例如在表达式 b[0][0] 中,您将获得未定义的行为。

【讨论】:

  • 好的,我看到数据类型不匹配。但它是如何导致崩溃的呢?
  • @user2070804 因为它错误。您使用了错误的指针类型,因此具有无效的别名,因此您的程序在使用该指针时会调用 undefined behavior。因此,该程序格式错误并且可能崩溃。(在这种情况下,很可能会这样做)。 +1,顺便说一句,关于答案
  • 格式不正确,可能会崩溃。好的,我知道了。仍然没有解释为什么会崩溃。语句 "board[r_itr][c_itr]" 将始终读取一个字节,对吗?
【解决方案2】:

问题是对于二维矩阵,表达式unsigned char[][]unsigned char ** 不兼容。 C language FAQother question 将解释差异。

编译代码时,您应该看到如下警告。这是来自 gcc:

warning: passing argument 1 of 'draw_board' from incompatible pointer type

如果您想解决问题并保持draw_board() 不变,则需要将board 声明为unsigned char ** 并像这样分配内存:

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

#define     GRID_X              30
#define     GRID_Y              20

//unsigned char board[GRID_Y][GRID_X];
unsigned char **board;

void draw_board( unsigned char ** );
void print_board( unsigned char ** );

int main()
{
    board = (unsigned char **) malloc(sizeof(unsigned char *) * GRID_X);
    int i;
    for (i = 0; i < GRID_X; i++)
    {
        board[i] = (unsigned char *) malloc(sizeof(unsigned char) * GRID_Y);
    }

    draw_board( board );
    //getch();
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 2013-10-04
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    相关资源
    最近更新 更多