Run-Time Check Failure #2 - Stack around the variable 'cz' was corrupted.

来源:互联网 发布:拾色笔 淘宝 编辑:程序博客网 时间:2024/05/18 01:17

 http://www.codeguru.com/forum/showthread.php?t=299770

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/14e7318e-6fff-4d68-a823-9cbe7b7bc20a/

 

I am getting:

Run-Time Check Failure #2 - Stack around the variable 'LoggerThread' was corrupted.

I have searched as much as I can for a description of how to diagnose, but I have not found anything. I don't know how to determine the specific address that is being corrupted. If I knew that, then I could of course set a breakpoint on the condition of that changing.

I have found many answers about other instances of this error, but nothing that descibes how to diagnose this problem. All other problems were simple enough that the problem could be determined by looking at the code. I have looked at my code extensively and I don't see a problem. One of the previous answers I have found is Error: Stack corruption around the variable 'tm' but the current version of the program uses only default alignment.

This particular problem is a symptom of a problem that has had various other symptoms, most of which would be more difficult to diagnose. Therefore the problem is probably more subtle than most. I initially encountered the problem in a DLL project, but I wrote a console program to use and test the relevant code. It is the console version that I am debugging.

  • crescens2k - Posted on 2007年6月21日 8:46:56

    This problem is caused when you try to write too much data to a particular memory address. Typical causes are writing more to a string buffer than you have room for.

    ie

     

    void myfun()

    {

        char mybuf[10];

     

        strcpy(mybuf, "This is definitely more than 10 characters long, it will also cause a Run-Time Check");

    }

     

    Another cause of this is when you are using memset/ZeroMemory to initialise a structure or array with the wrong size.

     

    struct MyStruct

    {

        int var;

    };

     

    void myfun2()

    {

        MyStruct ms;

     

        ZeroMemory(&ms, 20); //since MyStruct is only one variable in the struct this will cause problems

    }

     

    A third possible problem is if you are accidentaly moving a pointer.

     

    void myfun3()

    {

        int a;

        int*b = &a;

     

        a++;

        *a = 20;

    }

     

    Of course, these problems are not so easy as above to find out, but I hope this will get you on the right track. But this happens and will break at the end of the function that the stack is corrupted in while it is returning. So the best place to look would be in the function that your LoggerThread variable is in.

  • Sam Hobbs - Posted on 2007年6月21日 13:30:28

    I have commented out everything in my main function except what is shown in the following, and I still get the same error. The error occurs at the end of the program, after the "return 0;". In other words, the debugger says that the line that the exception occurs at is the line with the curly braces at the end of main.

     

    Code Snippet

    int main(int argc, char* argv[]) {

    classLoggerThread LoggerThread;

    LoggerThread.Start();

    std::cout << "Started/n";

    LoggerThread.Stop();

    std::cout << "Stopped/n";

    return 0;

    }

     

  • Marius BancilaMVP - Posted on 2007年6月21日 14:33:53

    So you're saying that the above code produces the error? That is strange, but tells me the problem is inside classLoggerThread.

     

    What I can tell you is that I have experienced this problem several times after switching from VC++ 2003 to VC++ 2005. The cause were some TRACE calls with wrong arguments. The VC++ 2003 debugger didn't say anything, but in 2005 it raised that error for things like this:

    Code Snippet
    TRACE("this is a wrong format %d and something else %s", 10);

     

    I hope you spot the wrong string format above, or should I say the incorrect number of params for it.

     

    Perhaps it's something similar for you too.

     

  • Sam Hobbs - Posted on 2007年6月21日 14:54:23

     Marius Bancila wrote:
    So you're saying that the above code produces the error? That is strange, but tells me the problem is inside classLoggerThread.

    No, I am saying the opposite. It is crescens2k that said that the problem is in the same function that declares LoggerThread so I posted the code to show that the problem cannot be caused in that function. So I agree with you that it has to be in LoggerThread (classLoggerThread) somewhere.

     

     Marius Bancila wrote:
    What I can tell you is that I have experienced this problem several times after switching from VC++ 2003 to VC++ 2005.

    This error will never occur using VC 2003 since VC 2003 does not detect the problem. I learned that much by searching for answers.

     

     Marius Bancila wrote:
    The cause were some TRACE calls with wrong arguments.

     Marius Bancila wrote:
    Perhaps it's something similar for you too.

    I have looked for things like that. As I have already said, it is nothing that obvious.

  • Holger Grund [MSFT] - Posted on 2007年6月21日 16:36:48

    Since you should easily find out which memory address is affected (obviously, it's either before or after the LoggerThread variable), you could simply set a data breakpoint on it and wait for it to fire.

     

    I tend to calculate the address manually as the debugger's concept of active scopes isn't usually very helpful for the cases where you really need a watchpoint. So, just set a breakpoint at your containing the variable. Then get the address of the variable (e.g. Quick Watch "&LoggerThread") and set a data breakpoint on the address causing the problem (again, it will be either before or after the underlying memory of the variable).

     

    Of course, once you leave the function. You should disable or remove the data breakpoint as other code will use the stack for its purposes.

     

    -hg

  • Sam Hobbs - Posted on 2007年6月22日 13:00:50

    I hope it is that simple. It would be easier if the error message were to say if the problem is before or after.

    I think though that it can't be that simple if the corruption occured after, since that portion of the stack would be constantly changing. Correct? It is not a simple matter of catching modification of the stack at higher addresses than LoggerThread. If the stack is corrupted after, then it seems the corruption occurs so far after (LoggerThread) that the stack memory is not used out there. One thing I am unsure of is the cookies used to detect the corruption. I hope modification of stack memory by the debugger for that purpose does not make things confusing.

    If however the stack is corrupted before LoggerThread, then it is strange that there is not a more serious problem, but at least it should be easy to diagnose the problem using breakpoints as you suggest.

     

    I apologize for sounding as if I am criticizing. These questions are among those I was hoping I would get help with. I wiil use breakpoints as you suggest if I don't figure it out some other way.

  • Holger Grund [MSFT] - Posted on 2007年6月22日 16:18:31
     Sam Hobbs wrote:

    I hope it is that simple. It would be easier if the error message were to say if the problem is before or after.

    I think though that it can't be that simple if the corruption occured after, since that portion of the stack would be constantly changing. Correct? It is not a simple matter of catching modification of the stack at higher addresses than LoggerThread. If the stack is corrupted after, then it seems the corruption occurs so far after (LoggerThread) that the stack memory is not used out there. One thing I am unsure of is the cookies used to detect the corruption. I hope modification of stack memory by the debugger for that purpose does not make things confusing.

     

    I haven't looked at the implementation lately, but I think the mechanism is quite simple actually. The compiler allocates space around variables on the stack and fills it with magic values on function entry. Before leaving the function it generated code checks if the values in the gaps between the real variables is still allocated.

     

    The stack after the function prolog would look something like

     

    call arguments

    return address

    saved stack pointers

    ...

    <magic value> // either this byte : ((char*)&LoggerThread)-1

    LoggerThread

    <magic value> // or this byte is overwritten &LoggerThread+1

    ...

     

    I'm not sure that what I said was clear. Before and after refer to the location not the time of execution. So after entering the function, just set two data breakpoints. One at ((char*)&LoggerThread)-1 and one at &LoggerThread+1. The stack corruption happens somewhere in the execution of your function (or its callees).

     

     Sam Hobbs wrote:

    If however the stack is corrupted before LoggerThread, then it is strange that there is not a more serious problem, but at least it should be easy to diagnose the problem using breakpoints as you suggest.

     

     

    Again before and after where meant to refer to the memory location of the problem. So it's not really an important distinction. It's the same type of problem just at slightly different memory locations. So long your problem consistenly repros for the particular function the watchpoints should work just fine - again these shouldn't be set or at least not active while your function is not executing as the stack space will be allocated for other things. Once execution enters your function the relevant stack space is allocated to that function until it is left.

     

     Sam Hobbs wrote:

    I apologize for sounding as if I am criticizing. These questions are among those I was hoping I would get help with. I wiil use breakpoints as you suggest if I don't figure it out some other way.

     

    Hey, these data breakpoints are really not that hard to use ;-)

     

    -hg

  • Sam Hobbs - Posted on 2007年6月23日 5:26:11

     Holger Grund wrote:
    Hey, these data breakpoints are really not that hard to use ;-)

    Actually they are useless for me when I use my own system, which is only 350 MHz. On that system, even very simple programs run noticeably slow and any meaningful debugging is impossible. The problem I am encountering I am developing and debugging using a fast system, so the performance is not likely to be a probem, but that has been a problem for me in the past.

     

    One of us does not understand. First, I must correct what I said before; the stack is used in reverse of what I was thinking. I knew that but I forgot. In other words, for each item local appearing in a function, the addresses decrease. The processor's stack pointer register is decreased for each item put into it, which makes sense, because then the processor knows there is a problem when the register gets to zero or less.

    Yes, I certainly understand that the error message is referring to memory before and after LoggerThread.

    There is an important difference between stack memory before a function's allocations and after.

    So for example if we have:

    Code Snippet

    void Level3(int a) {
     char Local[4];
    std::cout << "In Level3 Local is at " << &Local << '/n';
    }

    void Level2(int a) {
     char Local[4];
    std::cout << "In Level2 Local is at " << &Local << '/n';
    Level3(3);
    }

    void Level1(int a) {
     char Local[4];
    std::cout << "In Level1 Local is at " << &Local << '/n';
    Level2(2);
    }

    int main(int argc, char* argv[]) {
     (void)argc, argv;
     char Local[4]="321";
     unsigned *pStack;
    _asm {mov pStack, esp}
    std::cout << "The stack is at " << pStack << '/n';
    std::cout << "In main Local is at " << &Local << '/n';
    Level1(1);
    return 0;
    }

     

    Then the ouput I get is:

    The stack is at 0012FF1CIn main Local is at 0012FF6CIn Level1 Local is at 0012FF0CIn Level2 Local is at 0012FEB0In Level3 Local is at 0012FE54

    Note that the addresses decrease. If I create a breakpoint using "{main,,} *(Local-256)" for 256 elements, then that breakpoint breaks constantly due to normal use of the stack. That makes debugging more difficult; are you aware of that problem?

     

    I have commented out so much code that the problem is not manifesting as the stack corruption problem. There is currently  another symptom that I will attempt to diagnose but if I need to, I will recreate this problem to diagnose it.

  • Sam Hobbs - Posted on 2007年6月23日 10:18:42

    I managed to cut the code down to a small sample that reproduces the problem, or at least a problem. The symptoms vary, but I think I have been getting clobbered by the same bug, whatever the bug is. See Bizarre bug using std:Surprisefstream and TRACEFILE.

  • Holger Grund [MSFT] - Posted on 2007年6月24日 22:19:07
     Sam Hobbs wrote:

     Holger Grund wrote:
    Hey, these data breakpoints are really not that hard to use ;-)

    Actually they are useless for me when I use my own system, which is only 350 MHz. On that system, even very simple programs run noticeably slow and any meaningful debugging is impossible. The problem I am encountering I am developing and debugging using a fast system, so the performance is not likely to be a probem, but that has been a problem for me in the past.

     

     

    You probably haven't set the breakpoints in the correct way (again you should calculate the address yourself and leave the context empty so that the hardware debug breakpoint registers can be used).

     

     Sam Hobbs wrote:

    One of us does not understand. First, I must correct what I said before; the stack is used in reverse of what I was thinking. I knew that but I forgot. In other words, for each item local appearing in a function, the addresses decrease. The processor's stack pointer register is decreased for each item put into it, which makes sense, because then the processor knows there is a problem when the register gets to zero or less.

    Yes, I certainly understand that the error message is referring to memory before and after LoggerThread.

    There is an important difference between stack memory before a function's allocations and after.

    So for example if we have:

    Code Snippet

    void Level3(int a) {
     char Local[4];
    std::cout << "In Level3 Local is at " << &Local << '/n';
    }

    void Level2(int a) {
     char Local[4];
    std::cout << "In Level2 Local is at " << &Local << '/n';
    Level3(3);
    }

    void Level1(int a) {
     char Local[4];
    std::cout << "In Level1 Local is at " << &Local << '/n';
    Level2(2);
    }

    int main(int argc, char* argv[]) {
     (void)argc, argv;
     char Local[4]="321";
     unsigned *pStack;
    _asm {mov pStack, esp}
    std::cout << "The stack is at " << pStack << '/n';
    std::cout << "In main Local is at " << &Local << '/n';
    Level1(1);
    return 0;
    }

     

    Then the ouput I get is:

    The stack is at 0012FF1CIn main Local is at 0012FF6CIn Level1 Local is at 0012FF0CIn Level2 Local is at 0012FEB0In Level3 Local is at 0012FE54

    Note that the addresses decrease. If I create a breakpoint using "{main,,} *(Local-256)" for 256 elements, then that breakpoint breaks constantly due to normal use of the stack. That makes debugging more difficult; are you aware of that problem?

  • 原创粉丝点击