【问题标题】:Why does my C program crash when assigning a value to an int pointer?为什么我的 C 程序在为 int 指针赋值时会崩溃?
【发布时间】:2013-03-03 03:58:52
【问题描述】:

我试图让一个函数获取一些从我的 main() 函数传递过来的整数指针并为它们赋值。但是,我的程序在分配值时崩溃。这是我的代码:

int computeMoveLocation(int* r, int* c, char* board)
{
    //some code up here
    *r = 0;    //This breaks the program
    *c = 0;
}

我不是要更改指针的地址——我是要更改所指向的整数的。但是,我显然做错了什么。

任何帮助将不胜感激。

编辑: 这是来自 main() 的相关代码。请让我知道我是否还应该包含其他任何内容。

int main()
{
    //initialization code
    //...

    while (1)
    {

        switch (MACHINE_STATE)
        {
            case COMPUTER_MOVE :
            {
               //check rows for three Xs
               //check columns for three Xs
               //check diagonals for three Xs
               //otherwise, move anywhere else
               int *r, *c;
               computeMoveLocation(r, c, board);
               computerMove(*r,*c, board);
               PREVIOUS_STATE = COMPUTER_MOVE;
               MACHINE_STATE = HUMAN_MOVE;
               break;
            }

            //Other cases
        }//end switch
    }//end while
}//end main

【问题讨论】:

  • 显示主函数以及你是如何传递指针的。
  • 请告诉我们您如何调用computeMoveLocation? r、c 和 board 传递什么?
  • 你是否分配了rcboard指向的内存?
  • 欢迎来到 Stack Overflow。请尽快阅读FAQ。对于这样的问题,问题不在于您显示的行;它要么在代码的“此处的一些代码”部分中,要么在调用此函数的代码中(或两者兼而有之)。您需要提供一个 SSCCE (Short, Self-Contained, Correct Example) 以便我们可以看到是什么导致了问题,因为问题不在您显示的代码中。
  • 上面的代码似乎没有错,您是否将正确的地址传递给函数,例如 compute(&var,&var1,&var2) 而不是 compute(var,var1,var2)

标签: c pointers pass-by-reference


【解决方案1】:

您正在传递指针,但您没有分配内存。所以它们指向内存中的一个随机位置。

int computeMoveLocation(int* r, int* c, char* board) {
    //some code up here
    *r = 0;    //This breaks the program
    *c = 0;
}

糟糕的主线:

int main() {
    int *r;
    int *c;
    char *board;
    // bad, passing in pointers but didn't allocate memory
    computeMoveLocation(r, c, board); 
    return 0;
}

好的主要#1:

int main() {
    int r = 5;
    int c = 5;
    char board = 'a';
    // fine, passing address of variables on stack
    computeMoveLocation(&r, &c, &board); 
    return 0;
}

很好的主要#2:

int main() {
    int *r = malloc(sizeof(int));
    *r = 5;
    int *c = malloc(sizeof(int));
    *c = 5;
    char *board = malloc(sizeof(char));
    *board = 'a';
    // fine, passing pointers that point to heap
    computeMoveLocation(r, c, board); 

    free(r);
    free(c)
    free(board);
    return 0;
}

【讨论】:

  • +1,很好的解释。 Nitpick:C 程序员通常避免强制转换 malloc 的返回值,除非为了 C++ 兼容性。
  • 哈哈,是的,这里是用 C++ 编译的 ^_^。已编辑。
  • @nneonneo 没有使用 -Wall 删除演员阵容警告?
  • @Jack:除非你的 C 编译器坏了,否则不会。另见stackoverflow.com/a/605858/1204143
【解决方案2】:
int *r, *c;
computeMoveLocation(r, c, board);
computerMove(*r,*c, board);

你定义了一个指针,但没有让它指向任何东西。因此,它是一个 wild未初始化 指针;像在 computeMoveLocation 中一样访问 *r 将导致未定义的行为(在您的情况下是崩溃)。

您必须初始化指针以指向已知的东西,或者只传递现有int 的地址:

int r, c;
computeMoveLocation(&r, &c, ...);

static int x, y; // static: only one instance of the variable exists
int *r = &x; // initialize pointers
int *c = &y;
computeMoveLocation(r, c, ...);

int *r = malloc(sizeof(int));
int *c = malloc(sizeof(int));
computeMoveLocation(r, c, ...);

在最后一种情况下,请确保之后free 内存。

【讨论】:

    【解决方案3】:

    您始终可以传递一个指针并修改指针所指向的值。这就是应该使用指针的方式。 但是,您还应该小心查看指针是否确实指向某物。指针应包含一个有效地址,即您可以更改其位置的值。如果您不确保这一点,则会导致未定义的行为。

    例如,当您调用 computeMoveLocation 函数时,您传递的地址应该是堆栈地址或堆地址。你可以看下面的代码来理解它。

    第一种可能性

    int r, c;
    char board;
    computeMoveLocation(&r,&c, &board);
    

    第二种可能性

    int *r, *c;
    char *board;
    
    r = malloc(sizeof(int));
    c = malloc(sizeof(int));
    board = malloc(sizeof(char));
    computeMoveLocation(r,c,board);
    

    请注意,char * 通常也用于将地址传递给字符数组,但是,在这样的用法中,通常要确保它是空终止的,或者也传递了数组的伴随长度。

    无论如何,您都可以通过简单的 google 搜索获得有关传递指针的更多详细信息。


    编辑 现在,您已经发布了调用 computeMoveLocation 的代码,您看到您应该根据上面显示的第二种可能性修改您的代码,因为您将 r 和 c 声明为指针,或者您应该将它们声明为整数并按照第一种方式调用可能性如上所示。但是,你没有做同样的事情导致未定义的行为。

    另外,在上面的例子中,我已经为板子分配了内存,但是,在你的情况下,如果它起源于其他地方并且在那里得到了适当的处理,那么它不需要被分配。

    【讨论】:

    • board 不必是 mallocd,因为它源自其他地方(可能是定义棋盘的数组)。
    • 在他发布调用computeMoveLocation的代码之前,我已经开始回答了。我编辑了我的答案以反映您的想法。但是,在我看来,他还应该检查董事会是否在其起源的任何地方正确创建。
    猜你喜欢
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    相关资源
    最近更新 更多