希望我正确地解释了这个问题,但是我遇到了一个奇怪的问题,我正在研究一个程序中的结构。简而言之,我有两个结构设置如下:
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.A
和D.B
被覆盖了执行程序。在我看来,由于结构的设计方式,如子结构中的两个值(即A.A
和A.B
)相同,事情运作正常;但是,当它们不同时,D.A
和D.B
值会在程序在更改为D.A
或D.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;
}
关于可能发生的事情的任何想法?
答案 0 :(得分:3)
编辑:以下代码片段不再适用,因为问题已多次更改。
它编译是令人惊讶的,除非在某处有ChildStructure
的前向引用或其他类型信息。纯正的引用也不应该编译,因为没有大小信息可供编译器在没有它的情况下为ParentStructure
分配正确的空间量。
struct ChildStructure {
int A;
int B;
};
struct ParentStructure {
struct ChildStructure A;
struct ChildStructure B;
struct ChildStructure C;
struct ChildStructure D;
};
此代码编译。
您是否有可能将结构传递给“按值”而不是“按引用”的功能?如果您通过引用传递它们,那么编译器是否可能会看到两种不同的类型ParentStructure
或ChildStructure
的定义,从而为程序的执行提供潜在的数据哈希?
通过将“按值”结构传递给要操作的函数,可以立即解释您所看到的行为。
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时执行都会暂停。这应该显示哪些代码行正在改变您的变量。