简体   繁体   中英

Struct member corrupted after passed but not after passed again

I'm having some very strange bug in my ANSI C program. I'm using debugger and I've observed that 'size' variable is corrupted in function 'doSthing.' Outside of 'doSthing' 'size' got a proper value, but inside 'doSthing' I've got a value nothing similar to what it should be, possibly some random data. This would be not be such a mystery but...

In 'doAnotherThing' which is called from 'doSthing' I get the proper value again. I suppose if it passes the correct value, it is not corrupted anyway, am I wrong? But then why does it have a different value?

The pointer in struct does not change inside the functions. Memory is allocated for both oTV and oTV->oT .

I really don't see what's happening here...

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

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


void doSthing(ownTypeVector* oTV)
{

...
    doAnotherThing(oTV);
...

}

Thanks for your comments, I collected all the code that contains control logic and data structures so that it compiles. It runs on in an embedded systems, that can receive characters from multiple sources, builds strings from it by given rules and after the strings are ready, calls a function that needs that string. This can also be a list of functions. This is why I have function pointers - I can use the same logic for a bunch of things simply by choosing functions outside the 'activityFromCharacters' function. Here I build a data structre with them by adding As, Bs and Cs to the AVector. Of course every one of these separate sources has their own static strings so that they do not bother each other.

The problem again in the more detailed version of the code:

'aV->size' has got a proper value everywhere, except 'handleCaGivenWay.' Before it gets calles, 'aV->size' is ok, in 'addA' 'aV->size' is ok, too. After leaving 'handleCaGivenWay' it is ok again.

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

your code shows that it hasn't any error... But i think you are doing mistake in getting the value of size in doSthing function. you are printing there its address. so concentrate on some pointer stuff..

Try printing the oTV->size just before the call and as the first statement in doSthing function. If you get the correct value in both print, then the problem is with the function doSthing . Problem could be better understood if you've shown the code that calls doSthing .

Searched a long time to find this. I found 2 problems, but dont know what exactly you are trying to accomplish so i cannot tell for certain that the fix'es i propose are what you intend.

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

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

First: You are inlining the array of pointers in the struct. What i think what you want and need is a pointer to a pointer array so that it can grow which is what you want in addA() i think. The line from addA() aV->a[aV->size]->size = 0; does not communicate your intention very well but it looks like you are trying to change the value beyond the last entry in the array and since it is inlined in the struct it would result to the separate field size by pure coincidence on some alignments; this is a very fragile way of programming. So what i propose is this. Change the struct to contain A** a; // pointer to pointer-array A** a; // pointer to pointer-array , malloc it initially and re-malloc (and copy) it whenever you need it to grow (in addA() ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM