C# 由于大量计算而导致堆栈溢出错误
我只是在为下面的代码寻找一个有效的方法,因为我得到了一个堆栈溢出错误,我提供了尽可能多的信息,但也许你不需要所有这些解释,但只是代码本身就足够了,任何帮助将不胜感激,让我得到这个错误 我试图做的是一次将一个算子Hueckel边缘检测算子应用到一个9x9区域,并对整个图像重复它。因此,它是一种常规的边缘检测基础。你可以在第二张图片上看到我的意思 函数a在另一个称为hueckel_运算符的函数中一次被调用8次,hueckel_运算符是一个递归函数,每次对x和y参数调用自身+5。这意味着,对于大图像和真正的问题MyImage[],即emgucv图像对象,将调用a。因为MyImage[]应该检查9x9矩阵中的每个像素,并计算其值,所以调用它的次数是函数a的69*j倍 函数input_i_y带来y坐标,还有另一个函数叫做input_i_x,它带来9x9矩阵的x坐标。我知道,把两个分开的函数作为另一个函数的参数是极端的,但我找不到更好的解决办法。hueckel磁盘类根据x,y坐标计算9个不同hueckel磁盘的公式。根据拟合精度,我们可以确定是否存在边缘 这是hueckel_运算符的终止条件C# 由于大量计算而导致堆栈溢出错误,c#,image-processing,stack-overflow,C#,Image Processing,Stack Overflow,我只是在为下面的代码寻找一个有效的方法,因为我得到了一个堆栈溢出错误,我提供了尽可能多的信息,但也许你不需要所有这些解释,但只是代码本身就足够了,任何帮助将不胜感激,让我得到这个错误 我试图做的是一次将一个算子Hueckel边缘检测算子应用到一个9x9区域,并对整个图像重复它。因此,它是一种常规的边缘检测基础。你可以在第二张图片上看到我的意思 函数a在另一个称为hueckel_运算符的函数中一次被调用8次,hueckel_运算符是一个递归函数,每次对x和y参数调用自身+5。这意味着,对于大图像
if (mod_width + counter4 + 10 >= MyImage.Width && mod_height + counter5 + 10 >= MyImage.Height)
{
goto EXIT2;
}
public void hueckel_operator(int counter2, int counter3)
{
counter2 = counter4;
counter3 = counter5;
int mod_width = MyImage.Width % 5;
int mod_height = MyImage.Height % 5;
if (mod_width + counter4 + 10 >= MyImage.Width && mod_height + counter5 + 10 >= MyImage.Height)
{
goto EXIT2;
}
else
{
if (mod_width + counter4 + 10 >= MyImage.Width)
{
if (counter5 == 1)
{
counter5 += 4;
}
else
{
counter5 += 5;
}
counter4 = 1;
}
if (counter4 == 1)
{
counter4 += 4;
}
else if(counter4 != 0)
{
counter4 += 5;
}
if (counter5 == 0 && counter4 == 0)
{
counter4 = 1;
counter5 = 1;
}
}
这是hueckel_运算符的开始和结束
if (mod_width + counter4 + 10 >= MyImage.Width && mod_height + counter5 + 10 >= MyImage.Height)
{
goto EXIT2;
}
public void hueckel_operator(int counter2, int counter3)
{
counter2 = counter4;
counter3 = counter5;
int mod_width = MyImage.Width % 5;
int mod_height = MyImage.Height % 5;
if (mod_width + counter4 + 10 >= MyImage.Width && mod_height + counter5 + 10 >= MyImage.Height)
{
goto EXIT2;
}
else
{
if (mod_width + counter4 + 10 >= MyImage.Width)
{
if (counter5 == 1)
{
counter5 += 4;
}
else
{
counter5 += 5;
}
counter4 = 1;
}
if (counter4 == 1)
{
counter4 += 4;
}
else if(counter4 != 0)
{
counter4 += 5;
}
if (counter5 == 0 && counter4 == 0)
{
counter4 = 1;
counter5 = 1;
}
}
这是hueckel_运算符的结尾
出口:
下面是函数a
public double a(int j, int counter6, int counter7)
{
double result = 0;
HueckelDisks hueckel_formula = new HueckelDisks();
counter6 = counter4;
counter7 = counter5;
for (int II = 0; II <= j ; II++)
{
for (KK = 1; KK < 69; KK++)
{
result += hueckel_formula.HueckelDisk(input_i_x(KK),input_i_y(KK),j) * MyImage[point_a, point_b].Intensity;
}
}
return result;
}
public int input_i_y(int y)
{
Tuple<int, int>[] myArray =
{
Tuple.Create(3,1),Tuple.Create(4,1),Tuple.Create(5,1),Tuple.Create(6,1),Tuple.Create(7,1),Tuple.Create(2,2),
Tuple.Create(3,2),Tuple.Create(4,2),Tuple.Create(5,2),Tuple.Create(6,2),Tuple.Create(7,2),Tuple.Create(8,2),
Tuple.Create(1,3),Tuple.Create(2,3),Tuple.Create(3,3),Tuple.Create(4,3),Tuple.Create(5,3),Tuple.Create(6,3),
Tuple.Create(7,3),Tuple.Create(8,3),Tuple.Create(9,3),Tuple.Create(1,4),Tuple.Create(2,4),Tuple.Create(3,4),
Tuple.Create(4,4),Tuple.Create(5,4),Tuple.Create(6,4),Tuple.Create(7,4),Tuple.Create(8,4),Tuple.Create(9,4),
Tuple.Create(1,5),Tuple.Create(1,5),Tuple.Create(2,5),Tuple.Create(3,5),Tuple.Create(4,5),Tuple.Create(5,5),
Tuple.Create(6,5),Tuple.Create(7,5),Tuple.Create(8,5),Tuple.Create(9,5),Tuple.Create(1,6),Tuple.Create(2,6),
Tuple.Create(3,6),Tuple.Create(4,6),Tuple.Create(5,6),Tuple.Create(6,6),Tuple.Create(7,6),Tuple.Create(8,6),
Tuple.Create(8,6),Tuple.Create(1,7),Tuple.Create(2,7),Tuple.Create(3,7),Tuple.Create(4,7),Tuple.Create(5,7),
Tuple.Create(6,7),Tuple.Create(7,7),Tuple.Create(8,7),Tuple.Create(9,7),Tuple.Create(2,8),Tuple.Create(3,8),
Tuple.Create(4,8),Tuple.Create(5,8),Tuple.Create(6,8),Tuple.Create(7,8),Tuple.Create(8,8),Tuple.Create(3,9),
Tuple.Create(4,9),Tuple.Create(5,9),Tuple.Create(6,9),Tuple.Create(7,9),
};
return myArray[y].Item2;
}
hueckel_算子方法的开头包含无限递归的可能来源的提示
public void hueckel_operator(int counter2, int counter3)
{
counter2 = counter4;
counter3 = counter5;
您可以不使用两个参数的值,而是立即为它们指定必须来自我们在发布的代码中看不到的字段的值
其余可见代码甚至没有引用这些参数
不可能确定错误是在哪里给出的,您发布的代码位,但是很可能这些真正驱动逻辑的字段值没有改变,或者没有以允许递归结束的方式改变
我想根本问题是你不能理解你自己的代码。您应该使用有意义的变量名,而不是counter2、counter3等,尝试以不同于参数的方式命名字段,避免重新指定参数,并仅定义实际使用的参数
我也会尝试摆脱goto。请查看在input_I_y之外创建myArray 它甚至可以是静态的,因为在调用之间它不会改变
// ...somewhereinside you Hueckel class
public Tuple<int, int>[] myArray { get; set; }
// Initialize it
public void InitializeHueckel()
{
CreateMyArray();
}
// and build it
public void CreateMyArray()
{
myArray = new Tuple<int, int>[] {
Tuple.Create(3, 1), Tuple.Create(4, 1), Tuple.Create(5, 1),
Tuple.Create(6, 1), Tuple.Create(7, 1), Tuple.Create(2, 2),
Tuple.Create(3, 2), Tuple.Create(4, 2), Tuple.Create(5, 2),
Tuple.Create(6, 2), Tuple.Create(7, 2), Tuple.Create(8, 2),
Tuple.Create(1, 3), Tuple.Create(2, 3), Tuple.Create(3, 3),
Tuple.Create(4, 3), Tuple.Create(5, 3), Tuple.Create(6, 3),
Tuple.Create(7, 3), Tuple.Create(8, 3), Tuple.Create(9, 3),
Tuple.Create(1, 4), Tuple.Create(2, 4), Tuple.Create(3, 4),
Tuple.Create(4, 4), Tuple.Create(5, 4), Tuple.Create(6, 4),
Tuple.Create(7, 4), Tuple.Create(8, 4), Tuple.Create(9, 4),
Tuple.Create(1, 5), Tuple.Create(1, 5), Tuple.Create(2, 5),
Tuple.Create(3, 5), Tuple.Create(4, 5), Tuple.Create(5, 5),
Tuple.Create(6, 5), Tuple.Create(7, 5), Tuple.Create(8, 5),
Tuple.Create(9, 5), Tuple.Create(1, 6), Tuple.Create(2, 6),
Tuple.Create(3, 6), Tuple.Create(4, 6), Tuple.Create(5, 6),
Tuple.Create(6, 6), Tuple.Create(7, 6), Tuple.Create(8, 6),
Tuple.Create(8, 6), Tuple.Create(1, 7), Tuple.Create(2, 7),
Tuple.Create(3, 7), Tuple.Create(4, 7), Tuple.Create(5, 7),
Tuple.Create(6, 7), Tuple.Create(7, 7), Tuple.Create(8, 7),
Tuple.Create(9, 7), Tuple.Create(2, 8), Tuple.Create(3, 8),
Tuple.Create(4, 8), Tuple.Create(5, 8), Tuple.Create(6, 8),
Tuple.Create(7, 8), Tuple.Create(8, 8), Tuple.Create(3, 9),
Tuple.Create(4, 9), Tuple.Create(5, 9), Tuple.Create(6, 9),
Tuple.Create(7, 9),
};
应该移除堆栈中的一些负载 堆栈溢出来自递归。您发布的代码不包含任何内容。因此,我们可能需要看到不同的代码。堆栈溢出通常与无界递归相关,即函数在没有导致递归终止的基本情况下不断调用自身。所以我会先检查你的代码是否正确。当代码是正确的,但计算仍然会导致堆栈溢出时,通常意味着您提出了一个效率非常低的算法,它永远不会在合理的时间内完成。最后,每次调用函数input时,它都会创建并初始化一个新数组。这并不能解释堆栈溢出,但速度会非常慢。@arx我正在编辑我的问题,你可以看到它是否有界,但它被阻塞了,并以x=70,y=1的速度抛出堆栈溢出,对于一张600x800的图片,这仍然不足以让其他人理解发生了什么。当出现堆栈溢出错误时,请尝试查看调用堆栈。您看到多少嵌套函数调用?如果没有超过69个,我会非常惊讶。请注意,每个递归调用都会使调用总数成倍增加。请检查在输入外部创建myArray,因为这可以是静态的,在调用之间不会更改。但是,老实说,这不是这里的总体问题。这只会使堆栈膨胀。您可以编写一个初始化函数,只创建一次myArray!我已经做了,正如你所说,它减少了负载,谢谢。@OutlawLemur它帮助了我一点,让我更好地理解了静态,但它并没有完全解决我的问题,但我接受它。是的,我真的不知道为什么,但我找到了这样的解决方案来解决以前的错误,但我修复了那些混乱的参数。但它再次抛出堆栈溢出,但这次是mod_width=MyImage.width%5;顺便说一下,hueckel_算子被调用134次,a被调用1197次。奇怪的是,它完成了图像的第一行x=75和y=5,我得到了所有必要的值,但在第二行的1/10处,它抛出了堆栈溢出异常。伊格
这意味着它甚至不能达到终止条件,因为终止条件是x=590,y=790。我很确定它甚至不能达到终止条件,因为hueckel_操作符只被调用了134次,而且完成整个图像的次数也很少。hueckel_操作员必须被呼叫600/9*800/9次。