Член структуры поврежден после передачи, но не после повторной передачи - PullRequest
1 голос
/ 05 августа 2011

У меня очень странная ошибка в моей программе ANSI C. Я использую отладчик, и я заметил, что переменная 'size' повреждена в функции 'doSthing.' За пределами «doSthing» «размер» получил правильное значение, но внутри «doSthing» у меня есть значение, не похожее на то, каким оно должно быть, возможно, некоторые случайные данные. Это не было бы такой загадкой, но ...

В doAnotherThing, который вызывается из doSthing, я снова получаю правильное значение. Я полагаю, если он принимает правильное значение, он не поврежден в любом случае, я ошибаюсь? Но тогда почему оно имеет другое значение?

Указатель в структуре не изменяется внутри функций. Память выделена как для oTV, так и для oTV->oT.

Я действительно не понимаю, что здесь происходит ...

typedef struct{
ownType     *oT[]   /* array of pointers */
int     size;
} ownTypeVector;

void doSthing(ownTypeVector* oTV);
void doAnotherThing(ownTypeVector* oTV);


void doSthing(ownTypeVector* oTV)
{

...
    doAnotherThing(oTV);
...

}

Спасибо за ваши комментарии, я собрал весь код, который содержит управляющую логику и структуры данных, чтобы он компилировался. Он работает во встроенных системах, которые могут получать символы из нескольких источников, строят из него строки по заданным правилам и после того, как строки готовы, вызывают функцию, которая нуждается в этой строке. Это также может быть список функций. Вот почему у меня есть указатели на функции - я могу использовать одну и ту же логику для множества вещей, просто выбирая функции вне функции activityFromCharacters. Здесь я строю структуру данных с ними, добавляя A-s, B-s и C-s к AVector. Конечно, каждый из этих отдельных источников имеет свои собственные статические строки, чтобы они не мешали друг другу.

Проблема снова в более подробной версии кода:

'aV-> size' имеет правильное значение везде, кроме 'handleCaGivenWay.' Прежде чем он получит вызовы, «aV-> size» в порядке, в «addA» «aV-> size» тоже в порядке. После выхода из handleCaGivenWay все снова в порядке.

#define                     NUMBER_OF_AS            1
#define                     NUMBER_OF_BS            5
#define                     NUMBER_OF_CS            10

typedef struct{
char    name[81];
} C;

typedef struct{
C               *c[NUMBER_OF_CS];   /* array of pointers */
int                     size;
int                     index;
} B;

typedef struct{
B *b[NUMBER_OF_BS];     /* array of pointers */
char    name[81];
int     size;
} A;

typedef struct{
A *a[NUMBER_OF_AS]; /* array of pointers */
int     size;
} AVector;

typedef struct {
char *string1;
char *string2;
} stringBundle;

typedef struct{
void (*getCharacter)(char *buffer);
void (*doSthingwithC)(stringBundle* strings,AVector* aV);
AVector*    aV;

} functionBundle;

void getCharFromaGivenPort(char *buffer)
{
//...
}

void addA(AVector * aV, stringBundle* strings)
{
            aV->a[aV->size]->size = 0;
            ++aV->size;

                int i = 0;

            if(strlen(strings->string2) < 81)
            {
                for(i;i<81;++i)
                {
                    aV->a[aV->size-1]->name[i] = strings->string2[i];
                }
            }
            else {report("Too long name for A:");
                    report(strings->string2);}
}


void handleCaGivenWay(stringBundle* strings,AVector* aV)
{
    A* a;
    a = NULL;
    if(aV->size) { a = aV->a[aV->size-1]; }

switch(1)
{
    case 1:     addA(aV,strings); break;
    case 2:     //addB()...

    default:                if (a && aV->size)
                                    {   //addC(a->thr[a->size-1],c);
                                    }

                            else report("A or B or C invalid");
                            break;
}
//handleCaGivenWay
}

void activityFromCharacters(stringBundle* strings,functionBundle* funcbundle)
{
        /* some logic making strings from characters by */
        /* looking at certain tokens */

        (* funcbundle->doSthingwithC)(strings,funcbundle->aV);
}
//activityFromCharacters

AVector* initializeAVector(void)
{
AVector* aV;

if (NULL == (aV = calloc(1,sizeof(AVector))))
    { report("Cannot allocate memory for aVector."); }

int i = 0;
int j = 0;
int k = 0;

for(i; i < NUMBER_OF_AS; ++i)
{
    if (NULL == (aV->a[i] = calloc(1,sizeof(A))))
            { report("Cannot allocate memory for As."); }

    aV->a[i]->size = 0;
    aV->a[i]->name[0] = 0;

    for(j; j < NUMBER_OF_BS; ++j)
        {
        if (NULL == (aV->a[i]->b[j] = calloc(1,sizeof(B))))
                        { report("Cannot allocate memory for Bs."); }

        aV->a[i]->b[j]->size = 0;

        for(k; k < NUMBER_OF_CS; ++k)
            {
            if (NULL == (aV->a[i]->b[j]->c[k] = calloc(1,sizeof(C))))
                            { report("Cannot allocate memory for Cs."); }
            }
        }
}

aV->size = 0;

return aV;
//initializeProgramVector
}

int main (void)
{
AVector* aV;
   aV = initializeAVector();


while(1)
{
    static stringBundle string;
        static char str1[81];
        static char str2[81];
        string.string1 = str1;
        string.string2 = str2;

        functionBundle funcbundle;
        funcbundle.getCharacter = &getCharFromaGivenPort;
        funcbundle.doSthingwithC = &handleCaGivenWay;
        funcbundle.aV = aV;

        activityFromCharacters(&string,&funcbundle);
}

//main
}

Ответы [ 3 ]

0 голосов
/ 05 августа 2011

Попробуйте напечатать oTV->size непосредственно перед вызовом и в качестве первого оператора в функции doSthing. Если вы получите правильное значение в обеих распечатках, то проблема в функции doSthing. Проблема может быть лучше понята, если вы показали код, который вызывает doSthing.

0 голосов
/ 05 августа 2011

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

typedef struct{
    A *a[NUMBER_OF_AS]; /* array of pointers */
    int     size;
} AVector;

// and in addA():
aV->a[aV->size]->size = 0;

Первое: вы встраиваете массив указателей в структуру. Я думаю, что вам нужно и нужно, это указатель на массив указателей, чтобы он мог расти, что вы и хотите в addA(), я думаю. Строка addA () aV->a[aV->size]->size = 0; не очень хорошо передает ваше намерение, но похоже, что вы пытаетесь изменить значение за пределами последней записи в массиве, и поскольку оно встроено в структуру, оно будет приведите к отдельному полю size чистым совпадением некоторых выравниваний; это очень хрупкий способ программирования. Так что я предлагаю это. Измените структуру так, чтобы она содержала A** a; // pointer to pointer-array, сначала загрузите malloc, а затем повторно переместите (и скопируйте) ее всякий раз, когда вам нужно ее увеличить (в addA()).

0 голосов
/ 05 августа 2011

ваш код показывает, что в нем нет ошибок ... Но я думаю, что вы делаете ошибку в получении значения размера в функции doSthing.Вы печатаете там свой адрес.так что сконцентрируйся на каком-то указателе ...

...