【问题标题】:Struct member corrupted after passed but not after passed again结构成员在通过后损坏,但在再次通过后没有损坏
【发布时间】:2011-10-20 16:57:39
【问题描述】:

我的 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);
...

}

感谢您的 cmets,我收集了所有包含控制逻辑和数据结构的代码,以便编译。它在嵌入式系统中运行,可以接收来自多个来源的字符,根据给定的规则从中构建字符串,并在字符串准备好后,调用需要该字符串的函数。这也可以是函数列表。这就是为什么我有函数指针的原因——我可以通过选择“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
}

【问题讨论】:

  • 发布一个完整的工作(错误不工作)示例。
  • 问题不在于您显示的代码,而在于您未显示的代码。
  • 真的很棘手。已经找了一个小时的bug了……

标签: c data-structures ansi corruption


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      找了很久才找到。我发现了 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-&gt;a[aV-&gt;size]-&gt;size = 0; 的行并不能很好地传达您的意图,但看起来您正在尝试更改数组中最后一个条目的值 beyond 并且因为它内联在结构中在某些对齐上纯巧合会导致单独的字段size;这是一种非常脆弱的编程方式。所以我建议的是这个。将结构更改为包含A** a; // pointer to pointer-array,最初对其进行malloc,然后在需要它增长时重新malloc(并复制)它(在addA()中)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-21
        • 1970-01-01
        • 2019-09-26
        • 1970-01-01
        • 2013-03-30
        • 1970-01-01
        相关资源
        最近更新 更多