C# 不会无缘无故地中断循环

发布于 2024-10-30 14:53:13 字数 7480 浏览 5 评论 0原文

我正在编写一些解析 Apache 配置文件的代码。

文件im解析:

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 [email protected]
    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 [email protected]
    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]);
            }
        }
    }

hosts 是一个 vHost[] 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;公共字符串值; }

vhostRules 基本上是一个保存键和值的类

现在的问题是 hosts[c].addRule(param[0], param[1]); ,您可以看到它在类 vhost 中再次调用 addRule ,即使我清空 addRule 所以里面没有代码,这仍然不会工作。

这是我可以显示问题的唯一方法,没有更小的方法可以复制,因为错误似乎与编译的最终结果有关

我找到的唯一方法是注释或删除 hosts[c].addRule( param[0], param[1]); 从我的代码中,它可以工作,但如上所述,当我清空它时,它不起作用,这在理论上是不正确的,

尽管代码确实如此,但不会发生错误,并且它仅运行循环一次,

不会发生任何错误,这包括无静默死亡、无异常、无冻结/崩溃

更新 更新的阅读器

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

[email受保护]"

I'm writing some code that parses an Apache config file.

The File im parsing:

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 [email protected]
    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 [email protected]
    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>

This is the parser method filePath is the path to the above file.

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]);
            }
        }
    }

hosts is a vHost[] vHost is as below

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;
            }
        }
    }
}

The vhostRules Object

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

and vhostRules is basicly a class to save key and value

Now the problem is hosts[c].addRule(param[0], param[1]); of the read file above as you can see its is calling addRule as above again inside class vhost even if i empty addRule so there is no code inside this still does not work.

This is the only way i can show the problem there is no smaller way to replicate as the error appears to be with the compiled end result

The only way i have found is the comment or remove the hosts[c].addRule(param[0], param[1]); from my code then it works but as above when i empty it, it does not work that is theoretically incorrect

Stepping though the code does as its does no error occurs and it only runs the loop once,

NO ERRORS OCCUR THIS INCLUDES NO SILENT DEATH NO EXCEPTIONS AND NO FREEZING/CRASHING

update
Updated reader

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

Provides output

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

The Break point info

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

[email protected]"

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

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

发布评论

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

评论(3

私野 2024-11-06 14:53:13

只是为了提供一个实际的答案:

我最初的猜测 - 这只是一个猜测,因为我们没有我们需要的所有信息 - 是循环中的某个地方抛出了异常。

我能看到的最有可能的异常候选是这一行:

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

vhost 类中的 addRule 方法做了一些非常时髦的事情,但同样,我们没有所有信息,所以我可以'不敢肯定地说。

我们需要什么

我们至少需要知道正在发生什么。是否抛出异常?它达到什么线?难道就这样悄无声息地死去吗?您单步执行过代码吗?

请帮助我们帮助您...

更新
因此,问题出在以下位置:

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

OR:

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;
    }

OR:

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 方法中的代码周围添加错误处理,并查看输出内容查看堆栈跟踪,检查行号,并向我们准确显示其中发生的情况。 。

Just to provide an actual answer on this:

My initial guess - and it is only a guess, as we don't have all the information we need - is that there is an exception being thrown somewhere within the loop.

The most likely candidate I can see for the exception is the line:

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

The addRule method within the vhost class does some pretty funky stuff, but again, we don't have all the info, so I can't say for sure.

What we need

We will at least need to know what is happening. Is an exception being thrown? What line does it get up to? Does it silently die? Have you stepped through the code?

Please, help us to help you...

Update
So, the issue is somewhere in:

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

OR:

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;
    }

OR:

Within the constructor of vhostRules, as shown by the line:

rules[counter] = new vhostRules();

Now, what is the key you are using for the key value pair within rules[]?

You could try
Changing the line:

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

to:

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

This will allow you to keep the common at the end of some of your lines... This is probably not causing your main issue, but it's likely to be an issue at least.

Update 2
Set a breakpoint after the line above (string[] param = line.Trim().Split(new char[] {' '}, 2);, and see what param is actually set to. Add a watch, see exactly what param[0] and param[1] are. I have a feeling they're OK, and it's actually somewhere within the addRule method that the exception is being thrown...

So again, add error handling around the code within the addRule method, and see what is being output. Look at the stack trace, check the line numbers, and show us exactly what is going on in there.

美男兮 2024-11-06 14:53:13

不是解决您的问题,但至少进行一些清理:更改此行:

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();
}

Not a solution to your problem, but at least some cleanup: change this line:

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

into

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

then you don't need to recopy that array every time you need to add an item, just .Add() it.

You might then change

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

into

using System.Linq;
public vhostRules[] getRules()
{
    return rules.ToArray();
}
感性不性感 2024-11-06 14:53:13

我想我找到了。您对每个虚拟主机定义中的每一行执行此代码:

/* 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 个空格分隔的值。对于所有这些都是如此除了最后一个:

我希望您得到一个 ArrayIndexOutOfBoundsException(或 .NET 中调用的任何内容),但似乎有什么东西吞掉了它。

I think I found it. You execute this code for each line in each virtual host definition:

/* 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]);

This assumes that every line contains at least 2 space-separated values. That's true for all of them except for the last one: </VirtualHost>.

I'd expect you to get an ArrayIndexOutOfBoundsException (or whatever that is called in .NET), but something seems to swallow that.

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