2011-04-01 57 views
0

希望我正確地解釋了這一點,但是我遇到了一個奇怪的問題,它與我正在處理的程序中的結構有關。總之,我有兩個結構設置如下:結構元素值在執行過程中被覆蓋

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,它們被覆蓋掉了durin g執行程序。在我看來,這是由於結構設計的方式,因爲子結構中的兩個值(即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;  
} 

不限關於可能發生什麼的想法?

+0

使用您的調試器支持數據斷點。 – 2011-04-01 01:36:11

+0

不是沒有看到(a)有問題的代碼(b)'(struct ChildStructure)'的定義。 – geekosaur 2011-04-01 01:38:14

+0

'ParentStructure.h'上面是否包含'ChildStructure.h'? – 2011-04-01 01:42:48

回答

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; 
} 

你會然後在main.c中使用命令行break main.c:6 6設置斷點,然後用命令run啓動程序。執行將在執行第6行之前暫停。現在,您可以使用命令watch parent.D.A設置一個觀察點。使用命令continue恢復執行。現在,每次parent.D.A被更改時,執行都會暫停。這應該告訴你哪些代碼行正在改變你的變量。

+0

因爲問題最終成爲結構中的變量之一,所以在程序執行過程中由於算法中的錯誤而意外更新。 'gdb'最終成爲了解錯誤出現的途徑之一。 – rjzii 2011-04-01 16:41:11

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. 
} 
+0

感謝您指出這一點,我已經更新了問題,以更準確地設置程序。我已經檢查過函數,它們都是通過引用傳遞的(即'struct ParentStructure * data')。 – rjzii 2011-04-01 01:38:17

+0

我不知道「ChildStructure」的前向聲明是否會讓編譯器認爲它是一個空的結構。 ala:'struct ChildStructure {};' – 2011-04-01 01:42:45

+0

@Andy Finkenstadt - 如果是這樣的話,整個程序不會像所有元素都被使用一樣工作嗎? – rjzii 2011-04-01 01:52:11