Может ли этот простой код C # привести к переполнению стека? - PullRequest
0 голосов
/ 10 февраля 2009

У меня есть библиотека классов, которая в основном записывает строку в текстовый файл. Одним из его методов является LogString (string str), так что мне просто интересно, основываясь на приведенной ниже функции, если я вызываю ее много раз, например, более 600 раз, вызывает ли это стекопоток?

    public void LogString(string str)
    {  
        try
        {
            if (filePathFilenameExists())
            {
                using (StreamWriter strmWriter = new StreamWriter(filePathFilename, true))
                {
                    strmWriter.WriteLine(str);
                    strmWriter.Flush();
                    strmWriter.Close();
                }
            }
            else
            {
                MessageBox.Show("Unable to write to file");
            }
        }
        catch (Exception err)
        {
            string errMsg = err.Message;
        }

    }

Ответы [ 13 ]

9 голосов
/ 10 февраля 2009

Это даже не похоже на рекурсивную функцию. Я не понимаю, как это может вызвать переполнение стека.

Чтобы переполнить стек, вы должны постоянно вызывать функции изнутри функций. Каждый раз, когда вы делаете это, все больше стекового пространства используется для возобновления вызывающей функции, когда вызываемая функция возвращается. Рекурсивные функции сталкиваются с этой проблемой, потому что они должны хранить несколько копий состояния одной и той же функции, по одной для каждого уровня рекурсии. Это также может происходить во взаимно рекурсивных функциях (A вызывает B, B вызывает A), и это может быть сложнее обнаружить, но я не думаю, что это так.

3 голосов
/ 10 февраля 2009

Нет, это не приведет к переполнению стека, но может вызвать другие исключения, если два разных потока попытаются записать в один и тот же файл. рассмотрите возможность использования lock, чтобы сделать его потокобезопасным, если это необходимо.

2 голосов
/ 10 февраля 2009

@ Франци Пенов предлагает полезные советы .
Пожалуйста, прочитайте это сообщение Раймонда Чена .
Он аккуратно объясняет , почему функция, на которую указывает исключение переполнения стека, не является виновником.

1 голос
/ 10 февраля 2009

Если вы действительно хотите найти своего виновника, вам нужно взглянуть немного глубже в стек вызовов и посмотреть, какие другие функции в нем есть. Точнее, ищите повторяющиеся следы.

Другой способ получить исключение переполнения стека, если ваш код выделяет большой кусок памяти в стеке. Вам приходилось иметь дело с большими структурами где-то в вашем коде?

0 голосов
/ 13 февраля 2009

Спасибо всем за вклады и извините за суматоху. Это была моя вина, потому что в моей программе есть рекурсия, которую я не знал. Причина, по которой я не узнал об этом, потому что я не продолжал отслеживать вызовы, пока программа не остановилась. Я всегда останавливал отладку, когда последний вызов был выполнен в этом последнем сценарии (последняя функция), пока прошлой ночью я не продолжал отладку, пока программа не остановилась, а затем я увидел, что было сделано много вызовов назад и вперед, поэтому на основе моего маленького программирования Опыт я делаю вывод, что это рекурсия.

0 голосов
/ 10 февраля 2009

Я думаю, что Пол Фишер прав, но это мой первый пост, и у меня нет представителя, чтобы комментировать его ответ.

Та же теория в моих словах; Ваша вызывающая функция вызывает переполнение стека. Он помещает свои копии в стек до тех пор, пока он не окажется на относительно коротком расстоянии от конца. На некоторой "N-1" -й рекурсивной итерации вызывающей функции глубина стека вашей LogString достаточна для того, чтобы вызвать переполнение, поскольку тогда вы окажетесь на довольно коротком расстоянии от конца стека. filePathFilenameExists (), вероятно, имеет более глубокий максимальный стек, чем большинство других методов в вызывающей функции, и этого достаточно, чтобы выделить LogString как счастливчика, который ловит исключение.

Если оставить в стороне теорию, ваша проблема должна быть очевидна при выводе LogString, если он вызывается откуда-то повторно. Это и просмотр вашего стека в отладчике IDE.

0 голосов
/ 10 февраля 2009

Здесь смешно еще кое-что, потому что выложенный код практически не может вызвать переполнение стека.

  • Как выглядит остальная часть вашего стека вызовов, когда выдается исключение переполнения стека?
  • Является ли filePathFileName полем или свойством? Если это собственность, вы делаете что-нибудь в своем добытчике? Возможно, снова звоните LogString(String)?
0 голосов
/ 10 февраля 2009
    public bool filePathFilenameExists()
    {
        if (File.Exists(filePathFilename))
        {
            return true;
        }
        else
        {
           MessageBox.Show("Can not open Existing File.");
           return false;
        }
    }
0 голосов
/ 10 февраля 2009

Это функция filePathFileNameExists, которую Шон считал рекурсивной.

    public bool filePathFilenameExists()
    {
        if (File.Exists(filePathFilename))
        {
            return true;
        }
        else
        {
           MessageBox.Show("Can not open Existing File.");
           return false;
        }
    }
0 голосов
/ 10 февраля 2009

Единственная проблема, о которой я мог подумать, это то, что в этой функции происходит что-то безумное, и вы не перечисляете код для filePathFilenameExists ()

...