-3

Apache 構成ファイルを解析するコードを書いています。

解析中のファイル:

NameVirtualHost *:80

#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "c:/Apache2/docs/dummy-host.example.com"
    ServerName dummy-host.example.com
    ServerAlias www.dummy-host.example.com
    ErrorLog "logs/dummy-host.example.com-error.log"
    CustomLog "logs/dummy-host.example.com-access.log" common
</VirtualHost>

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "c:/Apache2/docs/dummy-host2.example.com"
    ServerName dummy-host2.example.com
    ErrorLog "logs/dummy-host2.example.com-error.log"
    CustomLog "logs/dummy-host2.example.com-access.log" common
</VirtualHost>

これはパーサー メソッドです。 filePath は上記のファイルへのパスです。

public void readFile(string filePath)
    {
        /* read the file path provided */
        StreamReader reader = new StreamReader(filePath);
        string content = reader.ReadToEnd();

        /* remove the comments from the file */
        string[] lines = content.Split('\n');
        string newContent = "";
        foreach(string line in lines){
            char[] chars = line.ToCharArray();
            if(chars[0] != '#'){
                newContent += line+"\n";
            }
        }

        /* search for Virtual hosts and save them */
        string regEx = "<VirtualHost [^>]*>[^<]*</VirtualHost>";
        MatchCollection coll = Regex.Matches(newContent, regEx, RegexOptions.IgnoreCase);
        string[] vhosts = new string[coll.Count];
        int counter = 0;

        /* go though them and save them into a string array */
        foreach (Match match in coll)
        {
            vhosts[counter] = (match.Value);
            counter++;
        }

        /* set the number of vhosts */
        hosts = new vhost[vhosts.Count()];

        /* go though the string array */
        for (int c = 0; c < vhosts.Count(); c++ )
        {

            MessageBox.Show("hi");

            /* set the host string to current vhost string */
            string host = vhosts[c];
            /* get the lines from the vhost */
            string[] lines2 = host.Split('\n');
            /* create the new save object in the array of vhosts */
            hosts[c] = new vhost();
            /* tell the console what were proccessing */
            Console.WriteLine((c+1).ToString() + " of " + vhosts.Count().ToString());
            /* for each line add the rule to the correct vHost via the counter for looping though the vhosts */
            for (int i = 0; i < lines2.Count(); i++)
            {
                /* set the string line to the line were currently on */
                string line = lines2[i];
                /* get rid of whitespace and split on the space (' ')*/
                string[] param = line.Trim().Split(' ');
                /* provde the current vHost number and the key and value in the config file */
                hosts[c].addRule(param[0], param[1]);
            }
        }
    }

hostsvHostはvHost[]以下の通りです

class vhost
{
    public vhostRules[] rules = new vhostRules[1];

    public string getRuleValue(string key)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key == Rule.key)
                return Rule.value;
        }
        return "";
    }

    public vhostRules getRule(string key)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key == Rule.key)
                return Rule;
        }
        return new vhostRules();
    }

    public vhostRules[] getRules()
    {
        return rules;
    }

    public void addRule(string key, string rule)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        int counter = 0;
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            rules[i] = Rule;
            counter++;
        }
        rules[counter] = new vhostRules();
        rules[counter].key = key;
        rules[counter].value = rule;
    }

    public void removeRule(string key)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key != Rule.key)
                rules[i] = Rule;
        }
    }

    public void changeRule(string key, string value)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            if (key != Rule.key)
            {
                rules[i] = Rule;
                rules[i].value = value;
            }
        }
    }
}

vhostRules オブジェクト

class vhostRules { public string key; public string value; }

基本的にキーとvhostRules値を保存するクラスです

問題はhosts[c].addRule(param[0], param[1]);上記の読み取りファイルにあります。addRule を空にしても、addRuleクラス内で再び上記のように呼び出していることがわかります。vhost

これは、エラーがコンパイルされた最終結果にあるように見えるため、複製するより小さな方法がないという問題を示すことができる唯一の方法です

私が見つけた唯一の方法は、コメントを削除するかhosts[c].addRule(param[0], param[1]);、コードから削除すると機能しますが、上記のように空にすると機能せず、理論的には正しくありません

エラーは発生せず、ループは 1 回だけ実行されます。

エラーは発生しません これにはサイレントデスは含まれません 例外もフリーズ/クラッシュもありません

update 更新されたリーダー

try
{
    hosts[c].addRule(param[0], param[1]);
}catch (Exception e) { Console.WriteLine(e.Message); }

出力を提供します

1 of 2
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
2 of 2
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array
Index was outside the bounds of the array

ブレイクポイント情報

param = {string[2]} 
    [0] = "ServerAdmin" 
    [1] = "webmaste

r@dummy-host.example.com"

4

3 に答える 3

2

問題の解決策ではありませんが、少なくともいくつかのクリーンアップ: 次の行を変更します。

public vhostRules[] rules = new vhostRules[1];

の中へ

private List<vhostRules> rules = new List<vhostRules>();

アイテムを追加する必要があるたびにその配列を再コピーする必要はありません.Add()

あなたはそれから変わるかもしれません

public vhostRules[] getRules()
{
    return rules;
}

の中へ

using System.Linq;
public vhostRules[] getRules()
{
    return rules.ToArray();
}
于 2011-04-05T15:30:15.307 に答える
2

これについて実際の答えを提供するだけです:

私の最初の推測は、必要な情報がすべて揃っているわけではないため、推測にすぎませんが、ループ内のどこかで例外がスローされているということです。

例外の可能性が最も高い候補は次の行です。

hosts[c].addRule(param[0], param[1]);

クラス内の addRule メソッドvhostはかなり変わった処理を行いますが、ここでもすべての情報が揃っているわけではないので、はっきりとは言えません。

私たちの必要なもの

少なくとも何が起こっているのかを知る必要があります。例外がスローされていますか? それは何線までですか?黙って死ぬの?コードをステップ実行しましたか?

助けてください...

更新
したがって、問題は次の場所にあります。

string[] param = line.Trim().Split(' ');                
hosts[c].addRule(param[0], param[1]);            

また:

public void addRule(string key, string rule)
    {
        vhostRules[] currentRules = rules;
        rules = new vhostRules[currentRules.Count()];
        int counter = 0;
        for (int i = 0; i < currentRules.Count(); i++)
        {
            vhostRules Rule = currentRules[i];
            rules[i] = Rule;
            counter++;
        }
        rules[counter] = new vhostRules();
        rules[counter].key = key;
        rules[counter].value = rule;
    }

また:

次の行に示すように、 のコンストラクター内でvhostRules:

rules[counter] = new vhostRules();

では、 内のキーと値のペアに使用しているキーは何rules[]ですか?


行を変更してみてください:

string[] param = line.Trim().Split(' ');

に:

string[] param = line.Trim().Split(new char[] {' '}, 2);

これにより、一部の行の最後に を残すことができますcommon...これはおそらく主な問題の原因ではありませんが、少なくとも問題になる可能性があります

更新 2
上記の行 ( の後にブレークポイントを設定し、string[] param = line.Trim().Split(new char[] {' '}, 2);実際にどの param が設定されているかを確認します。ウォッチを追加し、param[0] と param[1] が何であるかを正確に確認します。例外がスローされているaddRuleメソッドのどこか...

もう一度、addRule メソッド内のコードの周りにエラー処理を追加し、何が出力されるかを確認します。スタック トレースを見て、行番号を確認し、そこで何が起こっているかを正確に示してください。

于 2011-04-05T13:58:00.557 に答える
1

見つけたと思います。各仮想ホスト定義の各行に対して次のコードを実行します。

/* get rid of whitespace and split on the space (' ')*/
string[] param = line.Trim().Split(' ');
/* provde the current vHost number and the key and value in the config file */
hosts[c].addRule(param[0], param[1]);

これは、すべての行に少なくとも 2 つのスペースで区切られた値が含まれていることを前提としています。これは、最後のものを除いてすべてに当てはまります: </VirtualHost>.

(または .NET で呼び出されるもの)を取得することを期待していますArrayIndexOutOfBoundsExceptionが、何かがそれを飲み込んでいるようです。

于 2011-04-05T14:48:28.663 に答える