Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Bug in Visual Studio 2005 compiler?

Bug in Visual Studio 2005 compiler?

Scheduled Pinned Locked Moved C / C++ / MFC
announcementcsharpvisual-studiodebuggingarchitecture
55 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A a_matseevsky

    I clearly demonstrated, what cased problem in particular. I can repeat it again. There was two local variables: _lrct$ = -212 ; size = 16 tv5476 = -204 ; size = 8 The next command rewrites 8 bytes of _lrct$ fst QWORD PTR tv5476[ebp] That's all info. Which data in particular was replaced and by what- means nothing. The only important fact is that data was replaced with something else.

    S Offline
    S Offline
    Stefan_Lang
    wrote on last edited by
    #32

    This is not the C/C++ source code. There is a reason Richard is asking for it: it is all too common among people working "close to the metal" to "over-optimize" their code in a way that is simply wrong, or leads the compiler to produce inieffective or incorrect code. I'm not saying you did that, but you wouldn't be the first nor would you be the last. Anyway, we can't decide where the error or bug is without seeing the actual C/C++ source code. Nor can anyone provide additional suggestions or help if you don't at the very least offer us the same information that your compiler got.

    GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

    1 Reply Last reply
    0
    • A a_matseevsky

      Thanks, boys, for yours comments, but I've just found the reason. And it did not make me happy. Really, great knowledge means great pain. Look at this small part of a stack frame: _lrct$ = -212 ; size = 16 tv5476 = -204 ; size = 8 Do you see something interesting here? A RECT structure of size 16 bytes and something too close to it- in fact, variable tv5476 partially overlaps RECT. And what command fst QWORD PTR tv5476[ebp] does? It rewrites half of my RECT. I can only hope, that it is the bug in my own Visual Studio. I'll reinstall it- may be, it will help (once I met something like tis- a "new" operator refused to work at all and re installation resolved this situation)

      S Offline
      S Offline
      Stefan_Lang
      wrote on last edited by
      #33

      There are a whole lot of questions that remain unanswered. Either may deliver the true reason for the bug you're experiencing. Compiler bugs are certainly possible, but rather unlikely. You should really look at the problem again and consider some or all of the following questions: 1. Where did you get the information that - _lrct$ refers to the start address of the RECT struct you're referring to - the RECT struct is really 16 bytes in size - the offsets you show are in fact relative to the same base address 2. Did you derive from your observation of these addresses that part of your data is overwritten, or did you check the actual RECT structure to verify that? 3. What are the original declarations of the C/C++ symbols corresponding to the two addresses _lrct$ and tv5476? 4. How were the two objects allocated? 5. Are you sure that one of them (the RECT) hasn't been deallocated in the meantime? Note that optimizers may discard variables before the end of their lifetime as seen in code if they realize it is no longer used! I'm sure I could think of more questions, but this could be much more productive if we could see the actual code ...

      GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

      L A 2 Replies Last reply
      0
      • S Stefan_Lang

        There are a whole lot of questions that remain unanswered. Either may deliver the true reason for the bug you're experiencing. Compiler bugs are certainly possible, but rather unlikely. You should really look at the problem again and consider some or all of the following questions: 1. Where did you get the information that - _lrct$ refers to the start address of the RECT struct you're referring to - the RECT struct is really 16 bytes in size - the offsets you show are in fact relative to the same base address 2. Did you derive from your observation of these addresses that part of your data is overwritten, or did you check the actual RECT structure to verify that? 3. What are the original declarations of the C/C++ symbols corresponding to the two addresses _lrct$ and tv5476? 4. How were the two objects allocated? 5. Are you sure that one of them (the RECT) hasn't been deallocated in the meantime? Note that optimizers may discard variables before the end of their lifetime as seen in code if they realize it is no longer used! I'm sure I could think of more questions, but this could be much more productive if we could see the actual code ...

        GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #34

        Did you see this message in the thread[^]? It (sort of) explains quite a lot.

        Veni, vidi, abiit domum

        S 1 Reply Last reply
        0
        • L Lost User

          Did you see this message in the thread[^]? It (sort of) explains quite a lot.

          Veni, vidi, abiit domum

          S Offline
          S Offline
          Stefan_Lang
          wrote on last edited by
          #35

          Umm ... yes ... I kind of see it now I think I'll go ... meditate or something

          GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

          A 1 Reply Last reply
          0
          • S Stefan_Lang

            Umm ... yes ... I kind of see it now I think I'll go ... meditate or something

            GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

            A Offline
            A Offline
            a_matseevsky
            wrote on last edited by
            #36

            Dear Stefan, it seems to me, that I have to remind you some theory. Local variables within some procedure may be addressed via ebp or esp. In my particular case they was addressed via ebp. It is much simpler to read such code, because ebp remains constant within a procedure. I some local variable is defined within some block, it becomes inaccessible, when eip leaves this particular block. Its place may be overwritten by something else, that's correct. But simultaneously debugger refuses to show this variable!!! But it showed it- therefore, lrct (16 byte RECT structure) was in its own block, was visible and accessible. But it was partially overwritten- 8 bytes was used as temporary storage for ST(0). That behavior cannot be taken as a normal one. And not lrct only- same fate waited h and maybe something else.

            S 1 Reply Last reply
            0
            • A a_matseevsky

              Dear Stefan, it seems to me, that I have to remind you some theory. Local variables within some procedure may be addressed via ebp or esp. In my particular case they was addressed via ebp. It is much simpler to read such code, because ebp remains constant within a procedure. I some local variable is defined within some block, it becomes inaccessible, when eip leaves this particular block. Its place may be overwritten by something else, that's correct. But simultaneously debugger refuses to show this variable!!! But it showed it- therefore, lrct (16 byte RECT structure) was in its own block, was visible and accessible. But it was partially overwritten- 8 bytes was used as temporary storage for ST(0). That behavior cannot be taken as a normal one. And not lrct only- same fate waited h and maybe something else.

              S Offline
              S Offline
              Stefan_Lang
              wrote on last edited by
              #37

              a_matseevsky wrote:

              within a procedure

              This is just one of many bits of information you haven't really provided. Therefore the wide array of questions. I am well aware that many probably don't make a lot of sense to ask in your particular case if you see the exact code that the compiler used to produce the assembly. But as repeatedly mentioned, you haven't provided that code, so all we can do is guess and poke in the dark. In the meantime I've spotted the code that you posted in a different branch of this thread. It isn't the original code though, and doesn't provide sufficient insight to answer any of the questions I posted. You state that variant A doesn't work, but it doesn't use the max() function, so we have to assume that the assembler code generated from that doesn't match the bits you later found to be incorrect (if they are indeed that - we still do not know) In the code you posted you use some variables that are only referenced over a couple of lines. They may not in fact be stored in the stack at all! As a result, the debugger will not show their contents in the optimized release code. Similarly, if you define a struct with data that is never referenced, the compiler may decide to optimize away the unneeded bits, reducing the size of the struct. You haven't posted the definition of the struct, nor where it's accessed, so it's impossible to tell if that is the case. I could go on and easily bring up half a dozen or more other optimization techniques that you appear to be unaware of, and that will confound your ability to read useful information from the debugger alone within optimized code. But it's pointless.

              GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

              A 1 Reply Last reply
              0
              • S Stefan_Lang

                There are a whole lot of questions that remain unanswered. Either may deliver the true reason for the bug you're experiencing. Compiler bugs are certainly possible, but rather unlikely. You should really look at the problem again and consider some or all of the following questions: 1. Where did you get the information that - _lrct$ refers to the start address of the RECT struct you're referring to - the RECT struct is really 16 bytes in size - the offsets you show are in fact relative to the same base address 2. Did you derive from your observation of these addresses that part of your data is overwritten, or did you check the actual RECT structure to verify that? 3. What are the original declarations of the C/C++ symbols corresponding to the two addresses _lrct$ and tv5476? 4. How were the two objects allocated? 5. Are you sure that one of them (the RECT) hasn't been deallocated in the meantime? Note that optimizers may discard variables before the end of their lifetime as seen in code if they realize it is no longer used! I'm sure I could think of more questions, but this could be much more productive if we could see the actual code ...

                GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                A Offline
                A Offline
                a_matseevsky
                wrote on last edited by
                #38

                Well, I've just answered, but I do not see it... Well, let's go point by point Stefan_Lang wrote: You should really look at the problem again and consider some or all of the following questions: 1. Where did you get the information that - _lrct$ refers to the start address of the RECT struct you're referring to What do you think .asm files exist for? Compiler made them and I was able to see, where local and temporary variables was allocated. - the RECT struct is really 16 bytes in size Nice question, it comes to my mind too- but the same compiler was so kind, that showed me the size of a RECT structure - the offsets you show are in fact relative to the same base address You should know, that ebp register remains constant within any procedure! And in this particular case all local and temporary variables was addressed via ebp. 2. Did you derive from your observation of these addresses that part of your data is overwritten, or did you check the actual RECT structure to verify that? I saw it, running my prog under debugger and I know which command (fst) overwrote aforementioned RECT (in fact, only right and bottom). 3. What are the original declarations of the C/C++ symbols corresponding to the two addresses _lrct$ and tv5476? RECT lrct; the second variable is local storage, using to temporary storage of ST(0) 4. How were the two objects allocated? I wrote it, but I can repeat it again. _lrct=-212 and tv5476=-204 (number a decimal ones!) It means, that command fst tv5476[ebp] overwrites 8 bytes- one half of lrct structure. 5. Are you sure that one of them (the RECT) hasn't been deallocated in the meantime? Note that optimizers may discard variables before the end of their lifetime as seen in code if they realize it is no longer used! It would be possible, but in such case debugger refuses to show such variable and gives message like "expression cannot be evaluated". Moreover, compiler wouldn't let me to use a variable outside of the block, where it was declared. I'm sure I could think of more questions, but this could be much more productive if we could see the actual code ... You saw it. Answer a question, originally addressed to Richard- which variant (and why) refuses to work properly.

                S 1 Reply Last reply
                0
                • A a_matseevsky

                  Well, I've just answered, but I do not see it... Well, let's go point by point Stefan_Lang wrote: You should really look at the problem again and consider some or all of the following questions: 1. Where did you get the information that - _lrct$ refers to the start address of the RECT struct you're referring to What do you think .asm files exist for? Compiler made them and I was able to see, where local and temporary variables was allocated. - the RECT struct is really 16 bytes in size Nice question, it comes to my mind too- but the same compiler was so kind, that showed me the size of a RECT structure - the offsets you show are in fact relative to the same base address You should know, that ebp register remains constant within any procedure! And in this particular case all local and temporary variables was addressed via ebp. 2. Did you derive from your observation of these addresses that part of your data is overwritten, or did you check the actual RECT structure to verify that? I saw it, running my prog under debugger and I know which command (fst) overwrote aforementioned RECT (in fact, only right and bottom). 3. What are the original declarations of the C/C++ symbols corresponding to the two addresses _lrct$ and tv5476? RECT lrct; the second variable is local storage, using to temporary storage of ST(0) 4. How were the two objects allocated? I wrote it, but I can repeat it again. _lrct=-212 and tv5476=-204 (number a decimal ones!) It means, that command fst tv5476[ebp] overwrites 8 bytes- one half of lrct structure. 5. Are you sure that one of them (the RECT) hasn't been deallocated in the meantime? Note that optimizers may discard variables before the end of their lifetime as seen in code if they realize it is no longer used! It would be possible, but in such case debugger refuses to show such variable and gives message like "expression cannot be evaluated". Moreover, compiler wouldn't let me to use a variable outside of the block, where it was declared. I'm sure I could think of more questions, but this could be much more productive if we could see the actual code ... You saw it. Answer a question, originally addressed to Richard- which variant (and why) refuses to work properly.

                  S Offline
                  S Offline
                  Stefan_Lang
                  wrote on last edited by
                  #39

                  1.a) I realize that one is from the generated assembler code , but "I am able to see" is not an answer to my question. But never mind, you later wrote the original symbol is named _lrct, which I consider sufficient information at this point. Considering the fact that symbols starting with '_' are common within windows system libaries and the MFC, and 'rct' is a common name fragment used for windows rectangle types and variables, I presume this is the Windows RECT struct[^] that you're talking about? 1b) Are you saying you used the sizeof() function? That would be the only way I know of the compiler can 'tell' you as much. Or if you derived it from bits of the assembler code, I have to trust your word for it - I don't don't know how to extract that kind of information. 1c) it could have been different procedures, or even different threads. Before your more recent answers there was no way to tell. So this isn ot (part of) the cause of the problem. 2 As mentioned in another post: you can't trust debugger output in optimized code! Some variables may not be stored in the stack at all, others may be overwritten before they expire, and addresses used to view a particular element may not contain the correct value, or the most recent state of the variable, due to caching, or memory optimization. The only way to be sure of the actual, current state of a variable, is print it out to the console or maybe log file. 4 I meant memory allocation, as in whether they are on the stack, the heap, or temporaries. But in light of the other responses this is no longer important. 5: see 2. - Don't trust the debugger in optimized code. I still have some doubts the compiler has a bug - the symptom you describe is just too obvious. My guess is that it's a result of optimization. But with your responses you excluded a number of possible alternate causes. If you still feel it is a genuine bug you could report it to MS. However, I'm not sure whether they'll look into an 8 year old compiler when they have various newer versions to offer: if they find a bug, they'll probably only fix it in the newest version(s).

                  GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses bene

                  A 1 Reply Last reply
                  0
                  • S Stefan_Lang

                    a_matseevsky wrote:

                    within a procedure

                    This is just one of many bits of information you haven't really provided. Therefore the wide array of questions. I am well aware that many probably don't make a lot of sense to ask in your particular case if you see the exact code that the compiler used to produce the assembly. But as repeatedly mentioned, you haven't provided that code, so all we can do is guess and poke in the dark. In the meantime I've spotted the code that you posted in a different branch of this thread. It isn't the original code though, and doesn't provide sufficient insight to answer any of the questions I posted. You state that variant A doesn't work, but it doesn't use the max() function, so we have to assume that the assembler code generated from that doesn't match the bits you later found to be incorrect (if they are indeed that - we still do not know) In the code you posted you use some variables that are only referenced over a couple of lines. They may not in fact be stored in the stack at all! As a result, the debugger will not show their contents in the optimized release code. Similarly, if you define a struct with data that is never referenced, the compiler may decide to optimize away the unneeded bits, reducing the size of the struct. You haven't posted the definition of the struct, nor where it's accessed, so it's impossible to tell if that is the case. I could go on and easily bring up half a dozen or more other optimization techniques that you appear to be unaware of, and that will confound your ability to read useful information from the debugger alone within optimized code. But it's pointless.

                    GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                    A Offline
                    A Offline
                    a_matseevsky
                    wrote on last edited by
                    #40

                    Stefan_Lang wrote: In the meantime I've spotted the code that you posted in a different branch of this thread. It isn't the original code though, and doesn't provide sufficient insight to answer any of the questions I posted. You state that variant A doesn't work, but it doesn't use the max() function, so we have to assume that the assembler code generated from that doesn't match the bits you later found to be incorrect (if they are indeed that - we still do not know) What do you mean, writing "it isn't the original code?" That I copied it from somewhere or what? I never stated, that variant A does not work. It is your idea. I asked, which works and which not (and why). You was not able to answer this question and preferred to ignore it. In the code you posted you use some variables that are only referenced over a couple of lines. They may not in fact be stored in the stack at all! As a result, the debugger will not show their contents in the optimized release code. Similarly, if you define a struct with data that is never referenced, the compiler may decide to optimize away the unneeded bits, reducing the size of the struct. You haven't posted the definition of the struct, nor where it's accessed, so it's impossible to tell if that is the case. All fields of the RECT structute was later used. If compiler decided that they are no more in use, it is just its bug. RECT structure is so well-known, that i did not placed its definition here. It contents 4 fields of type long- top, left, right and bottom. Just 16 bytes. I ran release version under debugger and I saw all assembler commands and order of their execution. Therefore, I know which variables was not stored in a stack and which temporary variables (which I did not declared!) was stored and where. I could go on and easily bring up half a dozen or more other optimization techniques that you appear to be unaware of, and that will confound your ability to read useful information from the debugger alone within optimized code. But it's pointless. Pointless is to repeat things like "there are more things on the Earth, on the heaven, than any dreamt of in our philosophy". What makes you think that I do not know about optimization? Stop walking around and answer to one simple question: why local variable, visible and accessible, was overwritten? You cannot name at least one more or less credible reason. If it is not visible, I couldn't get access to it and debugger wouldn't show it. Just this situation happens with variables, which are used in

                    S 1 Reply Last reply
                    0
                    • S Stefan_Lang

                      1.a) I realize that one is from the generated assembler code , but "I am able to see" is not an answer to my question. But never mind, you later wrote the original symbol is named _lrct, which I consider sufficient information at this point. Considering the fact that symbols starting with '_' are common within windows system libaries and the MFC, and 'rct' is a common name fragment used for windows rectangle types and variables, I presume this is the Windows RECT struct[^] that you're talking about? 1b) Are you saying you used the sizeof() function? That would be the only way I know of the compiler can 'tell' you as much. Or if you derived it from bits of the assembler code, I have to trust your word for it - I don't don't know how to extract that kind of information. 1c) it could have been different procedures, or even different threads. Before your more recent answers there was no way to tell. So this isn ot (part of) the cause of the problem. 2 As mentioned in another post: you can't trust debugger output in optimized code! Some variables may not be stored in the stack at all, others may be overwritten before they expire, and addresses used to view a particular element may not contain the correct value, or the most recent state of the variable, due to caching, or memory optimization. The only way to be sure of the actual, current state of a variable, is print it out to the console or maybe log file. 4 I meant memory allocation, as in whether they are on the stack, the heap, or temporaries. But in light of the other responses this is no longer important. 5: see 2. - Don't trust the debugger in optimized code. I still have some doubts the compiler has a bug - the symptom you describe is just too obvious. My guess is that it's a result of optimization. But with your responses you excluded a number of possible alternate causes. If you still feel it is a genuine bug you could report it to MS. However, I'm not sure whether they'll look into an 8 year old compiler when they have various newer versions to offer: if they find a bug, they'll probably only fix it in the newest version(s).

                      GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses bene

                      A Offline
                      A Offline
                      a_matseevsky
                      wrote on last edited by
                      #41

                      Stefan_Lang wrote: 1.a) I realize that one is from the generated assembler code , but "I am able to see" is not an answer to my question. But never mind, you later wrote the original symbol is named _lrct, which I consider sufficient information at this point. Not exactly. In my code was a simple line like RECT lrct; compiler converted it into tv6649 = -332 ; size = 4 _lrct$ = -328 ; size = 16 _sf$204092 = -312 ; size = 8 There is no "sizeof"; yeah this operator made me problems once or twice. Look at how here lrct is placed- just correctly (it is another procedure! I rewrote that one, which caused problems, but as I wrote, there was difference not 16 bytes, but only 8. (I cannot show you the code, which caused problem- I rewrote it. Wrong allocation can be found now only here, in this tread) Considering the fact that symbols starting with '_' are common within windows system libaries and the MFC, and 'rct' is a common name fragment used for windows rectangle types and variables, I presume this is the Windows RECT struct[^] that you're talking about? Positive. But _ (and $ as well) was added by compiler. 1b) Are you saying you used the sizeof() function? That would be the only way I know of the compiler can 'tell' you as much. Or if you derived it from bits of the assembler code, I have to trust your word for it - I don't don't know how to extract that kind of information. I did not tell it- look up. Compiler wrote its size as a commentary in asm listing. 1c) it could have been different procedures, or even different threads. Before your more recent answers there was no way to tell. So this isn ot (part of) the cause of the problem. 2 As mentioned in another post: you can't trust debugger output in optimized code! Some variables may not be stored in the stack at all, others may be overwritten before they expire, and addresses used to view a particular element may not contain the correct value, or the most recent state of the variable, due to caching, or memory optimization. The only way to be sure of the actual, current state of a variable, is print it out to the console or maybe log file. What makes you think so? I watch at assembler code (well plus the source one), when I run release under debugger. And it demonstrates me just what it does. 4 I meant memory allocation, as in whether they are on the stack, the heap, or temporaries. But in light of the other responses this is no longer important. 5: see 2. - Don't trust the debugger in optimized code.

                      S 1 Reply Last reply
                      0
                      • A a_matseevsky

                        Stefan_Lang wrote: 1.a) I realize that one is from the generated assembler code , but "I am able to see" is not an answer to my question. But never mind, you later wrote the original symbol is named _lrct, which I consider sufficient information at this point. Not exactly. In my code was a simple line like RECT lrct; compiler converted it into tv6649 = -332 ; size = 4 _lrct$ = -328 ; size = 16 _sf$204092 = -312 ; size = 8 There is no "sizeof"; yeah this operator made me problems once or twice. Look at how here lrct is placed- just correctly (it is another procedure! I rewrote that one, which caused problems, but as I wrote, there was difference not 16 bytes, but only 8. (I cannot show you the code, which caused problem- I rewrote it. Wrong allocation can be found now only here, in this tread) Considering the fact that symbols starting with '_' are common within windows system libaries and the MFC, and 'rct' is a common name fragment used for windows rectangle types and variables, I presume this is the Windows RECT struct[^] that you're talking about? Positive. But _ (and $ as well) was added by compiler. 1b) Are you saying you used the sizeof() function? That would be the only way I know of the compiler can 'tell' you as much. Or if you derived it from bits of the assembler code, I have to trust your word for it - I don't don't know how to extract that kind of information. I did not tell it- look up. Compiler wrote its size as a commentary in asm listing. 1c) it could have been different procedures, or even different threads. Before your more recent answers there was no way to tell. So this isn ot (part of) the cause of the problem. 2 As mentioned in another post: you can't trust debugger output in optimized code! Some variables may not be stored in the stack at all, others may be overwritten before they expire, and addresses used to view a particular element may not contain the correct value, or the most recent state of the variable, due to caching, or memory optimization. The only way to be sure of the actual, current state of a variable, is print it out to the console or maybe log file. What makes you think so? I watch at assembler code (well plus the source one), when I run release under debugger. And it demonstrates me just what it does. 4 I meant memory allocation, as in whether they are on the stack, the heap, or temporaries. But in light of the other responses this is no longer important. 5: see 2. - Don't trust the debugger in optimized code.

                        S Offline
                        S Offline
                        Stefan_Lang
                        wrote on last edited by
                        #42

                        Interesting bit about the size comments. I don't recall ever seeing that - maybe a different setting... I trust that by now you realized that it is hard for us to reproduce the exact situation that led to the problem. I still hold that it's dangerous to deduce anything from optimized code, short of print statements or similar right in the original code: you'll never know just what the compiler did, and why, to optimize your memory footprint and performance. It's difficult to draw correlations from assembler to the original code, and the expectations that come with it. The code you posted doesn't look very complex. About the only optimization I would anticipate is that some of the local variables would be stored in register only, rather than on the stack. But then, optimizers work in mysterious ways - you'll never know what kind of optimization they can come up with until you see the code...

                        GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                        A 1 Reply Last reply
                        0
                        • A a_matseevsky

                          Stefan_Lang wrote: In the meantime I've spotted the code that you posted in a different branch of this thread. It isn't the original code though, and doesn't provide sufficient insight to answer any of the questions I posted. You state that variant A doesn't work, but it doesn't use the max() function, so we have to assume that the assembler code generated from that doesn't match the bits you later found to be incorrect (if they are indeed that - we still do not know) What do you mean, writing "it isn't the original code?" That I copied it from somewhere or what? I never stated, that variant A does not work. It is your idea. I asked, which works and which not (and why). You was not able to answer this question and preferred to ignore it. In the code you posted you use some variables that are only referenced over a couple of lines. They may not in fact be stored in the stack at all! As a result, the debugger will not show their contents in the optimized release code. Similarly, if you define a struct with data that is never referenced, the compiler may decide to optimize away the unneeded bits, reducing the size of the struct. You haven't posted the definition of the struct, nor where it's accessed, so it's impossible to tell if that is the case. All fields of the RECT structute was later used. If compiler decided that they are no more in use, it is just its bug. RECT structure is so well-known, that i did not placed its definition here. It contents 4 fields of type long- top, left, right and bottom. Just 16 bytes. I ran release version under debugger and I saw all assembler commands and order of their execution. Therefore, I know which variables was not stored in a stack and which temporary variables (which I did not declared!) was stored and where. I could go on and easily bring up half a dozen or more other optimization techniques that you appear to be unaware of, and that will confound your ability to read useful information from the debugger alone within optimized code. But it's pointless. Pointless is to repeat things like "there are more things on the Earth, on the heaven, than any dreamt of in our philosophy". What makes you think that I do not know about optimization? Stop walking around and answer to one simple question: why local variable, visible and accessible, was overwritten? You cannot name at least one more or less credible reason. If it is not visible, I couldn't get access to it and debugger wouldn't show it. Just this situation happens with variables, which are used in

                          S Offline
                          S Offline
                          Stefan_Lang
                          wrote on last edited by
                          #43

                          You should be aware that asking us which optimized code would work and which wouldn't, without posting the full code with declarations and optimizer settings is ludicrous. Therefore I decided to derive it based on you statements elsewhere: Variant B contains code that works by your own statement elsewhere. neither contains the max() funtion you refer to in your original question. So B is the working and A the not working - albeit not the original - version. Q. E. D. As for what is pointless or not: advice is only pointless if it isn't heeded. You believe that the debugger shows you every information correctly? It doesn't. It can't. It's physically impossible. I've dealt with optimizers 30 years ago: back then it wasn't to hard to anticipate what it would do, and in C you could often emulate pretty much the same without having to invoke the optimizer at all. meaning well optimized C code ran almost as well in debug mode as it did in release. I've dealt with optimizers 20 years ago, and it got more tricky. Still, well optimized C-code often turned out to be near optimal. I've dealt with optimizers 10 years ago, and the experience was very different: for one, the same optimizations in C code sometimes led to slower code, because it prevented the optimizer from performing extremely sophisticated optimizations that you'd never have thought of. Plus the size of the codebase made it impossible to optimize all of your code in that way anyway. At that point I stopped trying to optimize my C/C++ code by hand. Nowadays, when I check release code that doesn't do the same as debug code, I often find that half the variables aren't on stack, and some others get overwritten at unexpected moments. At least when I look at them through the debugger. It's the optimizer at work! What I usually do is pinpoint the location where everything goes south, then insert some print statements to ensure everything is as I expect it to be - and in 9 cases out of 10, something will not be as I expect it to be! And the debugger won't be able to show it! That's why I keep telling you not to trust the debugger - and looking at the assembler code doesn't change that you're using the debugger.

                          GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                          A 1 Reply Last reply
                          0
                          • S Stefan_Lang

                            You should be aware that asking us which optimized code would work and which wouldn't, without posting the full code with declarations and optimizer settings is ludicrous. Therefore I decided to derive it based on you statements elsewhere: Variant B contains code that works by your own statement elsewhere. neither contains the max() funtion you refer to in your original question. So B is the working and A the not working - albeit not the original - version. Q. E. D. As for what is pointless or not: advice is only pointless if it isn't heeded. You believe that the debugger shows you every information correctly? It doesn't. It can't. It's physically impossible. I've dealt with optimizers 30 years ago: back then it wasn't to hard to anticipate what it would do, and in C you could often emulate pretty much the same without having to invoke the optimizer at all. meaning well optimized C code ran almost as well in debug mode as it did in release. I've dealt with optimizers 20 years ago, and it got more tricky. Still, well optimized C-code often turned out to be near optimal. I've dealt with optimizers 10 years ago, and the experience was very different: for one, the same optimizations in C code sometimes led to slower code, because it prevented the optimizer from performing extremely sophisticated optimizations that you'd never have thought of. Plus the size of the codebase made it impossible to optimize all of your code in that way anyway. At that point I stopped trying to optimize my C/C++ code by hand. Nowadays, when I check release code that doesn't do the same as debug code, I often find that half the variables aren't on stack, and some others get overwritten at unexpected moments. At least when I look at them through the debugger. It's the optimizer at work! What I usually do is pinpoint the location where everything goes south, then insert some print statements to ensure everything is as I expect it to be - and in 9 cases out of 10, something will not be as I expect it to be! And the debugger won't be able to show it! That's why I keep telling you not to trust the debugger - and looking at the assembler code doesn't change that you're using the debugger.

                            GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                            A Offline
                            A Offline
                            a_matseevsky
                            wrote on last edited by
                            #44

                            Stefan_Lang wrote: Therefore I decided to derive it based on you statements elsewhere: Variant B contains code that works by your own statement elsewhere. neither contains the max() funtion you refer to in your original question. So B is the working and A the not working - albeit not the original - version. Q. E. D. Again- I never claimed, which variant works and which does not. It was my question. And what "not the original version" means? I made my own investigation since the time, when I asked my first question. I changed code many times. I found, that no min nor max are not the source of the problem. There is no need in demonstrating of the rest of original code- it is the same for A and B. The difference is only here, in these few lines. And my question was- how could it be- both variants are correct. So you cannot answer to my question. Should I send you the answer or you will think for a while? As for what is pointless or not: advice is only pointless if it isn't heeded. You believe that the debugger shows you every information correctly? It doesn't. It can't. It's physically impossible. Why? Which part is hidden? Pipelines? Debugger demonstrates me all what I need to understand the core of situation. You must work really hard, if you want to cheat (or to trick- whichever word do you prefer) debugger. It happens mostly with self-modified code. I've dealt with optimizers 30 years ago: back then it wasn't to hard to anticipate what it would do, and in C you could often emulate pretty much the same without having to invoke the optimizer at all. meaning well optimized C code ran almost as well in debug mode as it did in release. I've dealt with optimizers 20 years ago, and it got more tricky. Still, well optimized C-code often turned out to be near optimal. I've dealt with optimizers 10 years ago, and the experience was very different: for one, the same optimizations in C code sometimes led to slower code, because it prevented the optimizer from performing extremely sophisticated optimizations that you'd never have thought of. Plus the size of the codebase made it impossible to optimize all of your code in that way anyway. At that point I stopped trying to optimize my C/C++ code by hand. More than strange idea. Hi-level optimization cannot be performed by compiler. Low-level usually yes, but not always. Nowadays, when I check release code that doesn't do the same as debug code, I often find that half the variables aren't on stack, and some others get overwritten at unex

                            1 Reply Last reply
                            0
                            • A a_matseevsky

                              I can only recommend to you reread the whole discussion. I do know now, where the problem is. OK, compiler is absolutely stable. No problem with it. But it works incorrectly. It reserves some places in a stack for temporary variables. In fact, these variables stores content of co-processor's registers. Some of such temporary variables overlap (partially or completely) another local variables. It might be no problem- some local variables are visible only within some block, not within the whole procedure. If execution of code leaves some block (part of code within such {} brackets), all variables, declared within this block, becomes inaccessible and their place in a stack may be rewritten by another local variable. But compiler creates exe file, which performs this op even when some local variable is visible and accessible!!! And it happens not only with RECT structure, but with some of other local variables too. I saw this process, when I was running release version under debugger. Look up, where I placed piece of my code. Variable "h" was rewritten at least once. If it is not a compiler's bug, I'm definitely an elefant.

                              J Offline
                              J Offline
                              jschell
                              wrote on last edited by
                              #45

                              a_matseevsky wrote:

                              But it works incorrectly.

                              I suggest you reread my post - pointer bugs can have an impact FAR later in the code.

                              a_matseevsky wrote:

                              And it happens not only with RECT structure, but with some of other local variables too.

                              Don't know how to state this more clearly. Either you have a pointer bug or there is a compiler problem. If the latter then reducing the code will demonstrate it AND changing code far from it and unrelated will NOT impact it. Conversely if the former then you will not be able to reduce it because the code that you are looking at is not the source of the problem.

                              A 1 Reply Last reply
                              0
                              • S Stefan_Lang

                                Interesting bit about the size comments. I don't recall ever seeing that - maybe a different setting... I trust that by now you realized that it is hard for us to reproduce the exact situation that led to the problem. I still hold that it's dangerous to deduce anything from optimized code, short of print statements or similar right in the original code: you'll never know just what the compiler did, and why, to optimize your memory footprint and performance. It's difficult to draw correlations from assembler to the original code, and the expectations that come with it. The code you posted doesn't look very complex. About the only optimization I would anticipate is that some of the local variables would be stored in register only, rather than on the stack. But then, optimizers work in mysterious ways - you'll never know what kind of optimization they can come up with until you see the code...

                                GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                                A Offline
                                A Offline
                                a_matseevsky
                                wrote on last edited by
                                #46

                                Interesting bit about the size comments. I don't recall ever seeing that - maybe a different setting... Which compiler do you use? I only asked it to generate asm file with source code. All the rest was default settings (Sorry, later I added /Zi to generate debugger's symbols in release version. But it does not affect on generation of asm listing) I trust that by now you realized that it is hard for us to reproduce the exact situation that led to the problem. I do. You have no choice but to trust me (and stop looking where is light!). I still hold that it's dangerous to deduce anything from optimized code, short of print statements or similar right in the original code: you'll never know just what the compiler did, and why, to optimize your memory footprint and performance. It's difficult to draw correlations from assembler to the original code, and the expectations that come with it. But I do know exactly, what compiler does!!! What do you think asm listing exists for? Correlation is very simple and there are no problems with it. No matter, which sort of optimization is in use, resulting exe file must do the same things, and no matter, which optimization was used. The code you posted doesn't look very complex. About the only optimization I would anticipate is that some of the local variables would be stored in register only, rather than on the stack. But then, optimizers work in mysterious ways - you'll never know what kind of optimization they can come up with until you see the code... I saw. And without it I would never find, where the problem is. GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto) Even Straustrup claims, that there are situation, when goto is useful. Assume you need get out of nested loops... do { do { do { if(something is wrong) goto Skip_loops; } while (cond A) } while(cond B) } while(cond C) Skip_loops:;

                                1 Reply Last reply
                                0
                                • J jschell

                                  a_matseevsky wrote:

                                  But it works incorrectly.

                                  I suggest you reread my post - pointer bugs can have an impact FAR later in the code.

                                  a_matseevsky wrote:

                                  And it happens not only with RECT structure, but with some of other local variables too.

                                  Don't know how to state this more clearly. Either you have a pointer bug or there is a compiler problem. If the latter then reducing the code will demonstrate it AND changing code far from it and unrelated will NOT impact it. Conversely if the former then you will not be able to reduce it because the code that you are looking at is not the source of the problem.

                                  A Offline
                                  A Offline
                                  a_matseevsky
                                  wrote on last edited by
                                  #47

                                  There was no pointer bugs at all. I declared no pointers, but the structure- RECT lrct. And some local variables too. Compiler allocated them in a stack and added some temporary variables. In a such way: _lrct$=-212; tv5476=-204; It is a time bomb, which might explode in any time. And it did. That's all. So simple.

                                  J 1 Reply Last reply
                                  0
                                  • A a_matseevsky

                                    There was no pointer bugs at all. I declared no pointers, but the structure- RECT lrct. And some local variables too. Compiler allocated them in a stack and added some temporary variables. In a such way: _lrct$=-212; tv5476=-204; It is a time bomb, which might explode in any time. And it did. That's all. So simple.

                                    J Offline
                                    J Offline
                                    jschell
                                    wrote on last edited by
                                    #48

                                    a_matseevsky wrote:

                                    I declared no pointers

                                    You have a C++ application and do not use pointers ANYWHERE in the application? (Again is has NOTHING to do with pointers directly associated with the code where you think the bug is.)

                                    A 1 Reply Last reply
                                    0
                                    • J jschell

                                      a_matseevsky wrote:

                                      I declared no pointers

                                      You have a C++ application and do not use pointers ANYWHERE in the application? (Again is has NOTHING to do with pointers directly associated with the code where you think the bug is.)

                                      A Offline
                                      A Offline
                                      a_matseevsky
                                      wrote on last edited by
                                      #49

                                      I do not think where the bug is. I know it. I know exactly where variables was incorrectly allocated in stack and which command overwrote data. What are you talking about pointers? I do use them, of course, but they was not the cause. It is pointless to discuss here what might happens, ignoring all available info.

                                      J 1 Reply Last reply
                                      0
                                      • A a_matseevsky

                                        I do not think where the bug is. I know it. I know exactly where variables was incorrectly allocated in stack and which command overwrote data. What are you talking about pointers? I do use them, of course, but they was not the cause. It is pointless to discuss here what might happens, ignoring all available info.

                                        J Offline
                                        J Offline
                                        jschell
                                        wrote on last edited by
                                        #50

                                        a_matseevsky wrote:

                                        What are you talking about pointers?

                                        Either you didn't read what I said in my previous replies or didn't understand what I said.

                                        A 1 Reply Last reply
                                        0
                                        • J jschell

                                          a_matseevsky wrote:

                                          What are you talking about pointers?

                                          Either you didn't read what I said in my previous replies or didn't understand what I said.

                                          A Offline
                                          A Offline
                                          a_matseevsky
                                          wrote on last edited by
                                          #51

                                          jschell wrote: Either you didn't read what I said in my previous replies or didn't understand what I said. I did. It was you who did not read (or did not understand what he read). Look at quotes from your messages: I want to emphasize again that the pointer bug could be anywhere. The behavior you are seing is a symptom not a cause. Don't know how to state this more clearly. Either you have a pointer bug or there is a compiler problem. If the latter then reducing the code will demonstrate it AND changing code far from it and unrelated will NOT impact it. Conversely if the former then you will not be able to reduce it because the code that you are looking at is not the source of the problem. You have a C++ application and do not use pointers ANYWHERE in the application? (Again is has NOTHING to do with pointers directly associated with the code where you think the bug is.) There are empty words about what might happens. Nothing common with real situation. Compiler placed temporary variable too close to another one and when the tv5476 was used, RECT structure was partially overwritten. So simple. It is no pointer's problem- the compiler's one.

                                          J 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups