0

私は構造体の配列を持っており、それぞれが私が信号と呼ぶものを記述しています。私は自分の構造をこのように宣言しました:

 /* Structure for keywords */
 struct varStruct
 {
    char* varName;
    int varOccurence;
 } signals[MAX_SIGNALS];

私はファイルを分析し、私の場合はnewArrayNameと呼ばれる信号宣言を動的に見つけるループで作業しています。私がやりたいのは、読み取り信号がまだ含まれていない場合にのみ、読み取り信号を配列に追加することです。それ以外の場合は、varOccurence変数をインクリメントする必要があります。

これが私のコードですが、セグメンテーション違反があります(したがって、これ以上の情報はありません)...

    // We are in the loop that get the signals sequentially
    char* newArrayName = TheValueOfTheReadSignal.

    int i;
    // We browse all the array...
    for(i=0; i < MAX_SIGNALS; i++)
    {
        // If a signal already has the name of the currently-read signal, we inc its occurence
        if(strcmp(signals[i].varName, newArrayName) == 0)
        {
            signals[i].varOccurence++;
        }
        // Otherwise, we add a new signal with the read-name and an occurence corresponding to the value of a static variable that's incremented after each signal-reading.
        else
        {
            signals[index_Array].varName = newArrayName;
            signals[index_Array].varOccurence = index_Array;

        }
    }
     // We increment index_Array, which is a static int variable
       index_Array ++;
    // End of the loop that gets the signals 

これはセグメンテーション違反につながります。私はC言語があまり得意ではありません、私はそれが非常に苦手だとさえ言うでしょう。ここでの私の推測では、シグナル配列が初期化されていないため、signal [i]は彼にとって意味がありませんが、構造体の配列を初期化する方法がわかりません。多分それは別の理由です、私は知りません。

ご助力ありがとうございます。

4

3 に答える 3

2

問題は、最初の反復で、すべてのvarNameメンバーが(宣言さNULLれている場所に応じて)初期化されていないポインターになることです。signalsそれらが次のように初期化されていることを確認してくださいNULL

struct varStruct
{
    char* varName;
    int varOccurence;
} signals[MAX_SIGNALS] = { {0} };

そして、それがNULLに渡される前であるかどうかを確認してくださいstrcmp()

if(signals[i].varName && strcmp(signals[i].varName, newArrayName) == 0)

がNULLの場合varName、それ以上要素が入力されていないことを示し、入力してループから抜け出すことができます。

さらに、次のことを確認してください。

  • に割り当てられた値varNameが動的に割り当てられ(malloc()たとえばを使用して)、必要である限り存続し、不要になったfree() varNameときを覚えていること。
  • index_ArrayMAX_SIGNALSの要素を設定する前よりも少なくなりsignalsます。
于 2012-05-02T15:22:35.203 に答える
2
  1. 検索ループ自体の中に「新しい」エントリを作成しています。これにより、ほぼ毎回、すぐに新しいエントリが作成されます。すべての既存のエントリが一致しない場合にのみ、新しいエントリを作成する必要があります。つまり、ループが終了した後です。

  2. MAX_SIGNALS最初は配列のほとんどが空であるため、までループしないでください。最初のindex_Array要素だけが本物です。これにより、NULLポインターを使用して構造体を初期化し、それらをチェックする必要もなくなります。これは、初期化されていないエントリをループしないためです。

  3. あなたはindex_Array盲目的に増加しています。実際にエントリを追加した場合にのみインクリメントします。

お釣り:

// We are in the loop that get the signals sequentially
char* newArrayName = TheValueOfTheReadSignal.

int found_entry;
found_entry = FALSE; /* A flag that remembers if the entry has been found.  */

for(i=0; i < index_Array; i++)
{
    if(strcmp(signals[i].varName, newArrayName) == 0)
    {
        signals[i].varOccurence++;
        found_entry = TRUE;
        break;
    }
}
if (!found_entry)
{
    signals[index_Array].varName = newArrayName;
    signals[index_Array].varOccurence = index_Array++;
}
于 2012-05-02T15:23:12.190 に答える
1

記録されたエントリがないsignals場合、またはi記録されたエントリの数から1を引いた数よりも大きい場合、strcmp(signals[i].varName, newArrayName)は無効な(初期化されていないまたはNULL)ポインタを逆参照しようとしますsignals[i].varName

それを超えて、同じくらい(またはそれ以上)大きくindex_Arrayなるとすぐに、MAX_SIGNALS

// We browse all the array...
for(i=0; i < MAX_SIGNALS; i++)
{
    // If a signal already has the name of the currently-read signal, we inc its occurence
    if(strcmp(signals[i].varName, newArrayName) == 0)
    {
        signals[i].varOccurence++;
    }
    // Otherwise, we add a new signal with the read-name and an occurence corresponding to the value of a static variable that's incremented after each signal-reading.
    else
    {
        signals[index_Array].varName = newArrayName;
        signals[index_Array].varOccurence = index_Array;

    }
}
 // We increment index_Array, which is a static int variable
   index_Array ++;

配列の終わりを超えて書き込みます。これは未定義の動作であり、メモリの破損やセグメンテーション違反を直接、またはメモリの破損の結果として引き起こす可能性があります。

signals[index_Array]ループでは、異なる名前のシグナルを見つけるたびに書き込みを行いindex_Array、ループの実行後は、その名前のシグナルが既にあるかどうかに関係なく、毎回インクリメントします。信号をすでに録音しているかどうかを確認する必要があります。録音していない場合にのみ、新しいエントリを書き込んで増分しますindex_Array

// Check for newArrayName == NULL and exit or otherwise handle the situation if it is
// We browse all the array...
for(i=0; i < index_Array && i < MAX_SIGNALS; i++)
{
    // If a signal already has the name of the currently-read signal, we inc its occurence
    if(signals[i].varName != NULL && strcmp(signals[i].varName, newArrayName) == 0)
    {
        signals[i].varOccurence++;
        break; // we already have that signal, can stop looping
    }
}
// Check if i == MAX_SIGNALS
// if it is, we have no more space in the array,
// that needs handling
if (i == index_Array && index_Array < MAX_SIGNALS) {
    // We haven't had that signal before, record it
    signals[index_Array].varName = newArrayName;
    signals[index_Array].varOccurence = index_Array;
    // And increment index_Array, which is a static int variable
    index_Array ++;
}
于 2012-05-02T15:23:49.570 に答える