views:

601

answers:

17

I have a class library that mainly logs the string to text file. One of its method is LogString(string str) so I'm just wondering based on the function below if I call it for many times like over 600 times, does it cause stackoverflow?

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

    }
+9  A: 

That doesn't even appear to be a recursive function. I don't see how that would cause a stack overflow.

In order to overflow a stack you have to continually call functions from within functions. Every time you do this, more stack space is used to resume the calling function when the called function returns. Recursive functions run into this problem because they need to store multiple copies of the state of the same function, one for each level of recursion. This can also happen in mutually recursive functions (A calls B, B calls A) and it can be harder to detect, but I don't think that's the case here.

Kyle Cronin
Obviously filePathFilenameExists is implemented recursively :D
Sean Bright
+3  A: 

No, it won't cause stack overflow but it can cause other exceptions if two different threads will try to write into the same file. consider using lock to make it thread-safe if necessary.

lubos hasko
I use two threads, but one thread is disposed after 5 seconds when the program is executed thus only the main thread will continue to run the rest of the program. If it's shared violation, it should display message right? because I got this type of error before.
Bopha
A: 

I see, and that is what I thought too. But the thing is when my program calls the above method for number of times(many times), it throws an exception stackoverflow and the error always points to the statement that calls the above method. For example:

myLogObject.LogString(dataInformation);
Bopha
Could this be because some exception within the LogString method is causing a re-call of LogString (which in turns throws an expection which ...)?
strager
so far, I don't see any exception is thrown except the stackoverflow
Bopha
Can you try to determine if it's a certain amount of data passed to the function that causes the overflow? Or a certain number of times the function is called? Right now, without data, all we can do is guess.
Kyle Cronin
amound of data passed to the function maybe around 50 characters long. The function is called very alot because I have to log all the results to log file which very alot.
Bopha
A: 

According to Sean: Obviously filePathFilenameExists is implemented recursively :D – Sean

(Edit by Sean Bright - No, I was joking.)

is that reallly true? But filePathFilename is instantiated only one time during the class library instatiantion. For example:

    public TestLog(string path)
    {
        isDisposed = false;
        filePathFilename = path;
        CreateLog(path);
    }
Bopha
sorry D-Sean I misread your comment. You mentioned filePathFilenameExists not filePathFilename. I will go back and check to see if it occurs like u said. thanks.
Bopha
I think he's kidding. There's no reason for filePathFilenameExists to be recursive (and I very much doubt it is).
Kyle Cronin
A: 

Are you asking if it will it cause a stackoverflow or why does it cause a stackoverflow?

Stackoverflows (usually) happen when recursion goes slightly wrong.

JSmyth
A: 

In response to OP's update: The problem is probably with the caller method, and not LogString() itself. If the caller method is indeed a recursive method, then there is certainly a risk of stackoverflowing if the allocated stack size is not big enough.

Zach Scrivena
A: 

Calling this function will not cause a "stack overflow". You can only cause a stack overflow by a function calling itself recursively. I'll explain briefly:

When you call a function in a program, it creates a new entry on the "call stack". This contains a little information about the current function, the place it was called from, and the local variables of the function. This entry, as I said, is created when you call the function, but when you return from the function, throw an exception, or simply let the function reach its end, the system uses that information to return to the previous point of execution, then removes that entry from the call stack.

So, before you call your function, you might have on the stack:

.                           .
.                           .
.                           .
|                           |
+---------------------------+
| performComplexOperation() |
| return address            |
| local variables           |
| ...                       |
+---------------------------+

then, you call the LogString function:

.                           .
.                           .
.                           .
|                           |
+---------------------------+
| performComplexOperation() |
| return address            |
| local variables           |
| ...                       |
+---------------------------+
| LogString()               |
| return address            |
| local variables           |
| ...                       |
+---------------------------+

But after LogString completes, the code will return to performComplexOperation using the return address. The entry for LogString will be removed:

.                           .
.                           .
.                           .
|                           |
+---------------------------+
| performComplexOperation() |
| return address            |
| local variables           |
| ...                       |
+---------------------------+
       (this is where
    LogString used to be)

In a stack overflow, the space taken by the entries on the stack will exceed the space alloted for the stack by the language you're using*, and the program won't be able to create the entry for the function you're about to call.

* Not exactly, but close enough.

Paul Fisher
thanks for showing stack conceptual diagrams.
Bopha
Your stack is upside down! =D
Zach Scrivena
;) backwards think can't I but ,perhaps
Paul Fisher
based on everyone's respond this function will not cause stackoverflow, but the exception always points to that function called; or is it the error caused earlier?
Bopha
The error is CAUSED on LogString because it's exactly then where it runs out of stack space. But it's likely the function that calls LogString that is the culprit.
lc
I look at the call stack on IDE and I don't see anything weird for example. FunctionA calls FunctionB, FunctionA calls functionC, FunctionA calls FunctionD, and so on. FunctionA shows up alot because it reads each content from the array then pass to FunctionB,C,D. FunctionA will stop call when it
Bopha
when it matches out the size of array..
Bopha
A: 

Only problem I could think of is if you have something crazy going on in this function which you do not list code for filePathFilenameExists()

Chris Ballance
A: 

This is the function filePathFileNameExists that Sean thought was recursive.

    public bool filePathFilenameExists()
    {
        if (File.Exists(filePathFilename))
        {
            return true;
        }
        else
        {
           MessageBox.Show("Can not open Existing File.");
           return false;
        }
    }
Bopha
A: 
    public bool filePathFilenameExists()
    {
        if (File.Exists(filePathFilename))
        {
            return true;
        }
        else
        {
           MessageBox.Show("Can not open Existing File.");
           return false;
        }
    }
Bopha
You should not be displaying a message box in that method. Just return false.
Mitch Wheat
oh ok, thanks for pointing that out.
Bopha
A: 

For additional information. My class library is instantiated two times, but with two different varaibles(myLogObject and myLogSummaryObject)

Bopha
+1  A: 

If you realy want to find your culprit, you need to look a little bit deeper in the call stack and look what other functions are on it. More precisely, look for repetetive traces.

Another way to get the stack overflow exception is if your code allocates big chunk of memory on the stack. Do you happen to deal with big structures somewhere in your code?

Franci Penov
I create one global array that has size of 400, and three more ArrayList, but it's very small, maybe 30 max.The call stack, I look at it and it does has repetitive traces because number of calls from FunctionA to FunctionB is based on the size of array[400] which is the purpose of the program.
Bopha
It has to take each item in the array[400] and validate it then take next item out from array[400] until there is no more then will stop the calls.
Bopha
I reduce the arrays from 400 to 224, there is still error. When I reduce 224 to 43, it executes nicely without exception.
Bopha
If you post the call stack and some of the code that is controlled by the array, we might be able to help you with pinpointing the actual problem. Do you happen to be passing that array as a parameter to the recursing functions? You can try boxing the array in an object and passing reference to it.
Franci Penov
A: 

Something else is funny here because there's basically no way the code you've posted can cause a stack overflow.

  • What's the rest of your call stack look like when the stack overflow exception is thrown?
  • Is filePathFileName a field or a property? If it's a property, are you doing anything in your getter? Perhaps calling LogString(String) again?
lc
how can I find out the stack size when stackoverflow is thrown? Since I programmed, I've never thought about stack size because my program is not huge, but can u tell me how can I find out the stack based on your first question.
Bopha
filepathFileName is a public member data that is assigned inside the class library constructor.Not sure what u meant the 'your getter'logString will be called many times, but not an infinit loop calls.
Bopha
Are you using Visual Studio? If so, when the exception is thrown, you can look at the call stack window. If you see many calls to a certain function (particularly in a row), that's probably the culprit.
lc
if filePathFileName is a public member, then it doesn't matter. By 'getter', I meant if it were a property that you can specify a get function. If perhaps filePathFileName's get function was calling LogString, which was in turn calling filePathFileName's get function again...
lc
thanks for responding. In my program I declare global variable of array type then later in the function body(not constructor) I allocate array with size 224. Each array index corresponds to each case scenario. Each scenario is a function so each function will get called.
Bopha
When I run the code with size 224, it throws exception of stackoverflow, so I decided to reduce array size to 43. I comment out the rest of contents of the array also the functions that represent each array contents, and it works. No exception throwing.
Bopha
I run three or four times, still no exception. But when I run the code again with array size 43, but not comment out the functions that represent each array content then it throws exception(stackOverFlow) even though those functions never get called. Why is that?
Bopha
each function that represents each array content is implemented the same format structure, Read data from file then write data back to result file then move to next case scenario.
Bopha
What's the array of - structs, classes, ints? Did you take a look at the call stack like I suggested? Are you SURE those functions aren't getting called?? (There's no reason uncommenting a line that doesn't do anything should change anything...)
lc
A: 

I think Paul Fisher is right but this is my first post and I don't have the rep to comment on his answer.

The same theory in my words; your calling function is causing the stack overflow. It pushes copies of itself onto the stack until it's a relatively short distance from the end. On some "N-1"th recursive iteration of the calling function, the stack depth of your LogString is enough to cause the overflow, since you'd then be within a pretty short distance from the end of the stack. filePathFilenameExists() likely has a deeper maximum stack than most of the other methods in the calling function and is enough to single LogString out as the lucky guy who catches the exception.

Theory aside, your problem should be apparent by the output of LogString, assuming it's being called repetitively from somewhere. That and viewing your stack in the IDE debugger.

JP772
actuallly this is my first post as well.
Bopha
+2  A: 

@Franci Penov offers good advice.
Please read this post by Raymond Chen.
It neatly explains why the function that the stack overflow exception is pointing to is not the culprit.

Hamish Smith
A: 

Some differences to be observed. Stack overflow (stack exhaustion) not the same as stack buffer overflow

lsalamon
A: 

Thanks you everyone for the inputs and sorry for the hustle. It was my fault because my program has recursion which I didn't know. The reason I didn't find that out because I didn't continue to trace the calls until the program stopped. I always stopped the debug when the last call was made to that last case scenario(last function) until last night I continued to debug until the program stopped itself then I saw there were many calls were made back and forth so based on my little programming experience I conclude that is recursion.

Bopha