在执行期间覆盖结构元素值

时间:2011-04-01 01:30:10

标签: c gcc data-structures

希望我正确地解释了这个问题,但是我遇到了一个奇怪的问题,我正在研究一个程序中的结构。简而言之,我有两个结构设置如下:

ParentStructure.h

#include "ChildStructure.h"

struct ParentStructure {
    struct ChildStructure A;
    struct ChildStructure B;
    struct ChildStructure C;
    struct ChildStructure D;
};

ChildStructure.h

struct ChildStructure {   
    short A;
    short B;
};

我遇到的问题是ParentStructure中的一个变量(即ParentSturcutre.D)的值D.AD.B被覆盖了执行程序。在我看来,由于结构的设计方式,如子结构中的两个值(即A.AA.B)相同,事情运作正常;但是,当它们不同时,D.AD.B值会在程序在更改为D.AD.B后执行时恢复为原始值。

就如何调用函数而言,整体流程如下:

的main.c

#define WorkingDefaultAA 10 /* Program executes correctly */
#define WorkingDefaultAB 10

#define NonWorkingDefaultAA 10 /* Program does not execute correctly */
#define NonWorkingDefaultAB  8

struct ParentStructure *data;

int main(int argc, char *argv[]) {
    /* Set the default values for the data */
    while (true) {
        FunctionA(data);
    }
}

ProcessData.c

void FunctionA(struct ParentStructure *data) {
    /* Use data */
    FunctionB(data);
}

void FunctionB(struct ParentStructure *data) {
    data->D.A = 1;
    data->D.B = 1;    
}

关于可能发生的事情的任何想法?

2 个答案:

答案 0 :(得分:3)

编辑:以下代码片段不再适用,因为问题已多次更改。


它编译是令人惊讶的,除非在某处有ChildStructure的前向引用或其他类型信息。纯正的引用也不应该编译,因为没有大小信息可供编译器在没有它的情况下为ParentStructure分配正确的空间量。

struct ChildStructure {   
    int A;
    int B;
};

struct ParentStructure {
    struct ChildStructure A;
    struct ChildStructure B;
    struct ChildStructure C;
    struct ChildStructure D;
};

此代码编译。

您是否有可能将结构传递给“按值”而不是“按引用”的功能?如果您通过引用传递它们,那么编译器是否可能会看到两种不同的类型ParentStructureChildStructure的定义,从而为程序的执行提供潜在的数据哈希?

通过将“按值”结构传递给要操作的函数,可以立即解释您所看到的行为。

void ChangeAB( ChildStructure child ) {
    child.A = 3;
    child.B = 4;
}

void ChangeABByReference( ChildStructure& child ) {
    child.A = 3;
    child.B = 4;
}

int main(int argc, char *argv[]) {
    ParentStructure parent;
    parent.A.A = 0;
    parent.A.B = 2;
    ChangeAB(parent.A);
    // check values after returning from ChangeAB()
    ChangeABByReference(parent.A);
    // check values after returning - this time they should stick.
}

答案 1 :(得分:1)

使用调试器(如gdb)找出哪些代码行正在修改似乎正在恢复的变量。

在gdb中,您可以在表达式上设置一个观察点,每当表达式的值发生变化时,它将暂停程序的执行。然后,您可以查看堆栈跟踪以查看刚刚执行的代码行。

要有效地使用gdb,您需要使用调试符号编译代码。这是gcc中的-g标志。使用gdb my_buggy_executable将程序加载到调试器中。

设置观察点的最简单方法是首先在定义相关变量的范围内放置断点。假设你的main.c看起来像这样:

#include "ParentStructure.h"
#include "functions.h"

int main(){
    ParentStructure parent;
    parent.A.A = 0;
    parent.B.A = 0;
    parent.C.A = 0;
    parent.D.A = 0;
    parent.A.B = 0;
    parent.B.B = 0;
    parent.C.B = 0;
    parent.D.B = 0;

    functionA(&parent);

    return 0;
}

然后,您将使用命令break main.c:6在main.c的第6行设置断点,然后使用命令run启动该程序。执行将在第6行执行之前暂停。现在,您将使用命令watch parent.D.A设置观察点。使用命令continue继续执行。现在每次更改parent.D.A时执行都会暂停。这应该显示哪些代码行正在改变您的变量。