2011-08-05 22 views
1

ANSI Cプログラムに非常に奇妙なバグがあります。 私はデバッガを使用しており、 'サイズ'変数が関数 'doSthing'で破損していることがわかりました。 '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'関数の外の関数を選択することによって、同じロジックをたくさんのものに使うことができます。 ここでは、A-s、B-s、およびC-sをAVectorに追加することによって、データ構造を構築します。 もちろん、これらの別々のソースのすべてに静的な文字列があるため、お互いに気にしません。コードのより詳細なバージョンで再び

問題:

「AV-> size」は除いて、どこでも適切な値を持っている「handleCaGivenWay」。呼び出し前に 'aV-> size'は 'addA'で 'aV-> size'もOKです。 'handleCaGivenWay'を離れると、もう一度OKです。

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

完全な作業(err not working)の例を投稿してください。 – cnicutar

+0

http://sscce.org/ –

+0

問題は、表示するコードではなく、表示しないコードで発生します。 –

答えて

0

あなたのコードが...それはすべてのエラーをしていないことを示して しかし、私はあなたがdoSthing機能でサイズの値を得ることに間違いをやっていると思います。 その住所が印刷されています。だからいくつかのポインタのものに集中してください。

+0

あなたがいなくなったら、もっとコードをここに入れてください... –

0

oTV->sizeを呼び出し直前に、doSthingの最初のステートメントとして印刷してみてください。両方の印刷で正しい値を取得した場合、問題は関数doSthingにあります。 doSthingというコードを表示していれば、問題をよりよく理解できます。

0

これを見つけるために長い時間を検索しました。私は2つの問題を見つけましたが、正確に何を達成しようとしているのかわかりません。私が提案したfix'esがあなたが意図しているものであることを確かに伝えることはできません。

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())。

関連する問題