C 数组丢弃值,拾取垃圾

C 数组丢弃值,拾取垃圾,c,arrays,struct,gdb,garbage,C,Arrays,Struct,Gdb,Garbage,将值放入数组后,一步之后(感谢gdp),数组包含垃圾。之后的唯一步骤是将参数传递给函数: struct Vertex; typedef struct Vertex Vertex; struct Vertex { int sides[2][LENGTH]; int ends[2]; Vertex *children; Vertex *parent; }; void move(Vertex *node, int side, int place) { (38) int

将值放入数组后,一步之后(感谢gdp),数组包含垃圾。之后的唯一步骤是将参数传递给函数:

struct Vertex;
typedef struct Vertex Vertex;
struct Vertex {
    int sides[2][LENGTH];
    int ends[2];
    Vertex *children;
    Vertex *parent;
};

void move(Vertex *node, int side, int place) {
(38) int handfull = (*node).sides[side][place];
.....
}

int blah(Vertex *node, int side) {
.....
(103)    *((*node).children + i) = init_child(node);
(104)    move((*node).children + i, side, i);
(105)    blah((*node).children + i, opposingside);
.....
}
Vertex init_child(Vertex *node) {
    Vertex children[LENGTH];
    int i;
    int j;
    Vertex child = (*node);
    for (j = 0; j < 2; j++) {
        for (i = 0; i < LENGTH; i++)
            child.sides[j][i] = (*node).sides[j][i];
        child.ends[j] = (*node).ends[j];
    }
    child.children = children;
    child.parent = node;
    return child;
}
gdb告诉我以下几点:

(gdb) print (*node)
$7 = {sides = {{5, 5}, {0, 5}}, ends = {0, 1}, 
children = 0x7fffffffdfa0, parent = 0x7fffffffe110}
(gdb) print node
$8 = (Vertex *) 0x7fffffffe0c0
(gdb) print ((*node).children + i)
$9 = (Vertex *) 0x7fffffffdfa0
(gdb) print *((*node).children + i)
$10 = {sides = {{5, 5}, {0, 5}}, ends = {0, 1}, 
children = 0x7fffffffdf20, parent = 0x7fffffffe0c0}
(gdb) step
    move (node=0x7fffffffdfa0, place=0, side=0) at mancala.c:38
    38 int handfull = (*node).sides[side][place];
(gdb) print node
$11 = (Vertex *) 0x7fffffffdfa0
(gdb) print (*node)
$12 = {sides = {{-8160, 32767}, {4196818, 0}}, ends = {0, 1}, 
children = 0x7fffffffdf20, parent = 0x7fffffffe0c0}
我在第104行中断(称为
move
)。之后,
(*node).children+i
指向一个顶点结构,由$9和$10证明。我在
move
功能中迈出了一步。这将把我的顶点地址、返回地址等推到堆栈上,并开始使用
移动
函数。看看$11,我们看到顶点地址与$9中的地址相同,这很好。然而,在$12中,数组
.sides
现在充满了垃圾。其他一切都很好,但只是阵列中充满了垃圾

这是如何一步到位的?我一次只能调试一个步骤,所以我不知道现在该做什么


编辑:以下是init\u子函数:

struct Vertex;
typedef struct Vertex Vertex;
struct Vertex {
    int sides[2][LENGTH];
    int ends[2];
    Vertex *children;
    Vertex *parent;
};

void move(Vertex *node, int side, int place) {
(38) int handfull = (*node).sides[side][place];
.....
}

int blah(Vertex *node, int side) {
.....
(103)    *((*node).children + i) = init_child(node);
(104)    move((*node).children + i, side, i);
(105)    blah((*node).children + i, opposingside);
.....
}
Vertex init_child(Vertex *node) {
    Vertex children[LENGTH];
    int i;
    int j;
    Vertex child = (*node);
    for (j = 0; j < 2; j++) {
        for (i = 0; i < LENGTH; i++)
            child.sides[j][i] = (*node).sides[j][i];
        child.ends[j] = (*node).ends[j];
    }
    child.children = children;
    child.parent = node;
    return child;
}

问题是
init_child()
正在使用在函数作用域中创建的数组的地址初始化
子对象。当函数返回时,数组不再有效,因此返回的子结构指向无效对象

Vertex init_child(Vertex *node) {
Vertex children[LENGTH];            /* array variable on the stack */
/*...*/
child.children = children;          /* child pointing to local variable */
child.parent = node;
return child;
}
相反,例程应该动态分配内存,以便子进程指向内存,该内存的生命周期在函数返回后继续存在

Vertex init_child(Vertex *node) {
/*...*/
child.children = malloc(LENGTH*sizeof(*child.children));
child.parent = node;
return child;
}

你能把你的完整密码寄出去吗?或者是一个仍能说明问题的简化示例。谢谢!这就解决了问题。我想投更多的票,但显然我没有足够的代表权。实际上,我在调用init_child之前创建了空间,并将这些内容传递给init_child:这也是find,但是如果
LENGTH
很大,或者
Vertex
很大,则可能会超出操作系统为堆栈提供的内存量。