2

好的,所以我对 c 中的结构完全陌生,而且我遇到了一个对我来说似乎很奇怪的问题。
当使用它的指针将简单结构传递给函数时,该结构会自动采用该函数的其他参数之一,因为它是新数据。我不知道为什么会发生这种情况。。此时 move_walker() 应该什么都不做,对吧?

typedef struct {
    int x,
        y;
} walker_t;

walker_t* init_walker(int x, int y) {
    walker_t walker;
    walker.x = x;
    walker.y = y;
    walker_t *pointer = malloc(sizeof(walker));
    pointer = &walker;
    return pointer;
}

int move_walker(walker_t * walker, int direction) {
    return 0;
}

walker_t* walker;
walker = init_walker(8,2);

printf("%d %d\n", walker->x, walker->y); //will print '8 2'
move_walker(walker, 3);
printf("%d %d\n", walker->x, walker->y); //will print '0 3'

(我很确定这无关紧要,但这段代码实际上分布在多个文件中。)

4

6 回答 6

3

init_walker错了,因为它返回一个指向堆栈局部变量的指针,walker. init_walker一旦退出,该变量的内存就会被回收。你的第一个printf仍然有效,有点意外,因为你的walker变量的值在堆栈上仍然没有被触及。但是,一旦您在此之后进行任何函数调用,原始init_walker调用的堆栈帧就会被覆盖,并且walker指针现在指向一些随机垃圾。

当你malloc在里面init_walker时,你已经在堆上为你的walker_t. 所以,你应该这样做:

walker_t* init_walker(int x, int y) {
    walker_t *pointer = malloc(sizeof(walker_t));
    pointer->x = x;
    pointer->y = y;
    return pointer;
}
于 2013-02-19T11:49:01.923 回答
3

问题是您的walker指针指向无效的堆栈内存,因为init_walker有一个错误:您在堆栈上创建一个walker_t结构,然后保留内存malloc并将该内存的地址分配给pointer. 到目前为止,一切都很好。

但是,该行pointer = &walker不会结构从堆栈复制到新内存,而是pointer指向堆栈上的结构!&walker是 的地址walker,并将其分配给指针。您可能想要做的是复制结构。为此,您必须取消引用您的指针:

*pointer = walker

这应该使您的程序按预期工作。您还可以完全跳过堆栈上的结构:

walker_t* init_walker(int x, int y) {
    walker_t *walker = malloc(sizeof(walker_t));
    walker->x = x;
    walker->y = y;
    return walker;
}
于 2013-02-19T11:50:37.067 回答
2

您正在堆栈上创建结构对象。您需要使用

walker_t* init_walker(int x, int y) {
walker_t* walker = malloc(sizeof(walker_t));
...
return walker;
}

walker_t *pointer = malloc(sizeof(walker));
pointer = &walker;

您正在创建内存泄漏!您将新内存分配给 *pointer 并在将 &walker 分配给指针时丢失指针。

于 2013-02-19T11:48:17.660 回答
0
 walker_t* init_walker(int x, int y) {
    walker_t walker;
    walker.x = x;
    walker.y = y;
    walker_t *pointer = malloc(sizeof(walker));
    *pointer = walker;  /* here was the error. Copy the value not the adress */
    return pointer;
}

但它可以更简单:

walker_t* init_walker(int x, int y) {

    walker_t *pointer = malloc(sizeof(*pointer));
    pointer->x = x;
    pointer->y = y;       
    return pointer;
}
于 2013-02-19T11:49:29.567 回答
0

...或者,在对代码进行完整性检查后,您也可以编写:

typedef struct 
{
    int x,
    int y;
} walker_t;

void init_walker(walker_t* obj, int x, int y) 
{
   obj->x = x;
   obj->y = y;
}

walker_t walker;
init_walker(&walker, 8,2);
于 2013-02-19T13:00:11.740 回答
0

你的代码是把它的政体“非常奇怪”。

这将更好地工作......

walker_t *init_walker (int x, int y)
{
    walker_t *p_walker = (walker_t *)malloc (sizeof(walker));

    if (p_walker != NULL)
    {
        p_walker->x = x;
        p_walker->y = y;
    }
    return (p_walker);
}

然后free (walker)在你完成他们的时候打电话

于 2013-02-19T11:55:47.073 回答