结构成员在通过后损坏,但再次通过后未损坏

发布于 2024-11-28 10:57:15 字数 4573 浏览 3 评论 0原文

我的 ANSI C 程序中有一些非常奇怪的错误。 我正在使用调试器,并且观察到函数“doSthing”中的“size”变量已损坏。在“doSthing”之外,“size”得到了一个正确的值,但在“doSthing”内部,我得到了一个与应有的值完全不同的值,可能是一些随机数据。这并不是什么神秘的事情,但是......

在从“doSthing”调用的“doAnotherThing”中,我再次获得了正确的值。我想如果它传递了正确的值,它就不会被损坏,我错了吗?但为什么它有不同的价值呢?

struct 中的指针在函数内部不会改变。 内存被分配给oTVoTV->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”函数之外的函数,我就可以对很多事情使用相同的逻辑。 在这里,我通过将 As、Bs 和 Cs 添加到 AVector 来用它们构建一个数据结构。 当然,这些单独的源中的每一个都有自己的静态字符串,这样它们就不会互相干扰。

在更详细的代码版本中,问题再次出现:

除了“handleCaGivenWay”之外,“aV->size”在任何地方都有正确的值。在它被调用之前,“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
}

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 A-s, B-s and C-s 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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

波浪屿的海角声 2024-12-05 10:57:16

你的代码显示它没有任何错误...
但我认为你在获取 doSthing 函数中的 size 值时犯了错误。
你正在那里打印它的地址。所以专注于一些指针的东西..

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..

驱逐舰岛风号 2024-12-05 10:57:16

尝试在调用之前打印 oTV->size 并将其作为 doSthing 函数中的第一个语句。如果两次打印都得到正确的值,则问题出在函数 doSthing 上。如果您显示了调用 doSthing 的代码,则可以更好地理解问题。

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.

栀梦 2024-12-05 10:57:16

找了好久才找到这个。我发现了两个问题,但不知道您到底想要完成什么,所以我无法确定我提出的修复是否是您想要的。

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; // 指向指针数组的指针,最初对其进行 malloc,并在需要它增长时重新 malloc(并复制)它(在 addA() 中)。

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, malloc it initially and re-malloc (and copy) it whenever you need it to grow (in addA()).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文