Значения элементов структуры перезаписываются во время выполнения - PullRequest
0 голосов
/ 01 апреля 2011

Надеюсь, я объясняю это правильно, но у меня возникла странная проблема со структурой в программе, над которой я работаю.Короче говоря, у меня есть две структуры, настроенные следующим образом:

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

Есть идеи о том, что может происходить?

Ответы [ 2 ]

3 голосов
/ 01 апреля 2011

Редактировать: приведенные ниже фрагменты кода больше не применяются, поскольку вопрос менялся несколько раз.


То, что он компилируется, удивительно, если только где-то нет прямой ссылки или другой информации о типе для 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 голос
/ 01 апреля 2011

Используйте отладчик, такой как gdb, чтобы выяснить, какие строки кода модифицируют переменную, которая, по-видимому, возвращается.

В gdb вы можете установить точку наблюдения для выражения, которое будет приостанавливать выполнение программы каждый раз, когда изменяется значение этого выражения. Затем вы можете посмотреть на трассировку стека и посмотреть, какая строка кода только что выполнена.

Чтобы эффективно использовать GDB, вам необходимо скомпилировать код с отладочными символами. Это флаг -g в gcc. Загрузите вашу программу в отладчик с помощью 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;
}

Затем вы должны установить точку останова в строке 6 в main.c с помощью команды break main.c:6, а затем запустить программу с помощью команды run. Выполнение будет приостановлено до выполнения строки 6. Теперь вы должны установить точку наблюдения с помощью команды watch parent.D.A. Возобновите выполнение с помощью команды continue. Теперь выполнение будет приостанавливаться каждый раз, когда parent.D.A изменяется. Это должно показать вам, какие строки кода изменяют вашу переменную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...