CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

View Poll Results: How often have you used 'goto' in the last 5 years?

Voters
111. You may not vote on this poll
  • I use goto regularly.

    3 2.70%
  • I use goto occasionally.

    8 7.21%
  • I've used goto VERY occasionally.

    34 30.63%
  • I've never used goto at all.

    66 59.46%
Page 3 of 9 FirstFirst 123456 ... LastLast
Results 31 to 45 of 122
  1. #31
    Join Date
    Sep 2002
    Location
    Maryland - Fear The Turtle!
    Posts
    7,537
    Originally posted by j0nas
    Hmm... Yes, me too. How would such test/research be lead? Methods to use and so on...
    the only relevant thing would be a snippet of code showing the usage of goto in the product, but even then that's not relevant

    Just as this whole discussion is quite irrelevant, since we all don't work with each other. If we did then we could hit each other over the heads with the goto bat. All in all, I think the majority would be against using goto, but if you present a clear case where its usage is validated (and it really is per situation/usage) then I can't see myself arguing the point but I still would question the usage at first in a code review...again as pointed out, it's a matter of taste, and it all depends on how it's used...my first preference is not to use it. Tightly nested loops would probably be the only situation where I could validate it's use but there are many different ways to write a piece of code that does not have to jump out to a label.

    /Meh...just my opinion....blah

  2. #32
    Join Date
    Aug 2002
    Location
    United States
    Posts
    729
    well without a desire to be dragged into any of the several goto debates raging on the forums right now ....

    goto is evil and in c/c++ i view it as poor design, it has a place in other languages *asm as jmp or basic* but not here. i used it maybe once when i was first learning C after having done basic out of old habit but i still wish i hadn't lol. i voted never.

  3. #33
    Join Date
    Aug 2002
    Location
    Madrid
    Posts
    4,588
    Originally posted by Mick
    btw: I'm on the, never used goto, never saw the need to...but I never rule anything out...
    Exactly my situation. I've never had the need for a goto, so I'm doing fine without.
    Get this small utility to do basic syntax highlighting in vBulletin forums (like Codeguru) easily.
    Supports C++ and VB out of the box, but can be configured for other languages.

  4. #34
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664

    I give up. I'm hereby guilty of using goto statements in almost all of my code.



    Seriously, yes I use goto:s a lot (jumping to cleanup upon error) when I write C code. And yes, I think it's the right way of producing defensive C programs.

    Sam and others... Yes, maybe I did take many of the replies too seriously or didn't express myself well enough. I have problems with replies, in "open ended" questions, that sound like he or she is telling the pure truth. I'll try better next time.

    Have fun,
    Jonas

  5. #35
    Join Date
    Feb 2003
    Location
    Brazil
    Posts
    335
    I have never used, and never will.

    cheers

    Rabelo

  6. #36
    Join Date
    Aug 2002
    Location
    Madrid
    Posts
    4,588
    Originally posted by j0nas
    Seriously, yes I use goto:s a lot (jumping to cleanup upon error) when I write C code. And yes, I think it's the right way of producing defensive C programs.
    Can you explain why you need goto in your case? It would be interesting to know.
    Get this small utility to do basic syntax highlighting in vBulletin forums (like Codeguru) easily.
    Supports C++ and VB out of the box, but can be configured for other languages.

  7. #37
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    Originally posted by filthy_mcnasty
    goto is evil
    This has been said a couple of times. So is throw evil too? It seems to have similar drawbacks....

    ....and if not, why not?

  8. #38
    Join Date
    Feb 2003
    Location
    Brazil
    Posts
    335
    Because throw has only one door an only one destination, the catch block . there is only one way to you to get caught. Think as if catch was a label and you will realize what I mean.

    Rabelo

  9. #39
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    But goto only has one destination too. Of course, different goto's can have different destinations - but then, different throw's can also have different destinations.

    At least with goto, you can't jump out of the current function (you can't, can you?? I've never tried it). The problem with throw is that you can end up in a totally different function. To me, this seems to be just as unstructured - in fact, more so - than goto. So why is throw good, when goto is bad?

  10. #40
    Join Date
    Nov 2003
    Location
    Vienna, Austria
    Posts
    212
    You can't jump into a scope with goto (though some compilers seem to allow it at least within a function, but I think that the standard actually disallows it), so you can't jump into other functions.

    It's really hard to explain why throw is better. I think it is, I'm a fan of exceptions.
    throw is designed for error handling. As many people in this thread agree, the only really valid use for goto is error handling. Or at least it seems to me like all the people who actually use goto here have said they use it only for error handling. throw is better at error handling than goto. It can carry data, and you don't have to handle the error immediatly, when you probably don't have the means to handle it effectivly. Instead, you can let the stack unwind, cleaning all resources on the way thanks to RAII, and handle the error where appropriate. Provided good documentation of which functions throw which exceptions, this can be easy, maintainable and logical. I really like the way Java enforces exception handling or reporting.
    All the buzzt
    CornedBee

  11. #41
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652
    Originally posted by j0nas
    "...getting the application to a point where it is generally called 'bug-free' is much harder than using no 'goto' at all."
    Well...you quoted a little bit out of context. I think, I am not that far off while stating than many people using 'goto' are using it for a certain reason...because it simplifies jumping to a certain place in your application. However, it was quoted in relevance to the sample and it was not being assuming that everybody using 'goto' for such a reason.

    Originally posted by j0nas
    "Please tell us the name of your software product(s) where you have used goto regularly."
    This is simply a funny reaction of people who avoid using 'goto' in their applications and should not be taken that serious...

  12. #42
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    Originally posted by CornedBee
    it seems to me like all the people who actually use goto here have said they use it only for error handling.
    That's definitely been the only use I've ever put it to and, in my opinion (which is only a preference) the fact that it cannot be used to jump out of a function is it's main advantage.
    Originally posted by CornedBee
    throw is better at error handling than goto [...] you don't have to handle the error immediatly [...] Instead, you can let the stack unwind, cleaning all resources on the way thanks to RAII
    Really? I'm not familiar with RAII but it's never been my experience that throw invokes any kind of resource cleanup. What is RAII, out of interest? It sounds useful.

  13. #43
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652
    Originally posted by John E
    But goto only has one destination too. Of course, different goto's can have different destinations - but then, different throw's can also have different destinations.

    At least with goto, you can't jump out of the current function (you can't, can you?? I've never tried it). The problem with throw is that you can end up in a totally different function. To me, this seems to be just as unstructured - in fact, more so - than goto. So why is throw good, when goto is bad?
    Well...I know that it is personal flavor at the end, however, even the point that a thrown exception can be handled within a completely different part of the application is an advantage for a well-designed error handling routine. It gives you the possibility to handle an exception at the exact location where it makes the most sense to actually handle it.

    If an exception occurs in your application, there are two major thoughts you have to answer:
    • Can I fix the exception in order to continue with my application and still guarantee the integrity of the data?
    • Where can I fix the exception in order to guarantee this integrity of the data?

    Answering these questions might lead to the point that you might be able to keep the integrity of the data, however, only if the exception gets handled three functions up the stack simply because there you have all the necessary information available to keep the integrity of the data.

    It is hard to describe what makes the advantages of exception handling clear (at least for me and my English knowledge) and there is certainly a big impact of personal judgement on things involved. Certain aspects are obvious like CornedBee already pointed out. Overall, exception handling is rather the big picture - that is, you usually design such a system before you even program it.

    On the lowest level I agree though...throwing exceptions interrupts the program flow as well...

  14. #44
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652
    Originally posted by John E
    I'm not familiar with RAII but it's never been my experience that throw invokes any kind of resource cleanup. What is RAII, out of interest? It sounds useful.
    Well...it is not the exception handling itself (-> 'throw') that invokes RAII explicitly. 'RAII' stands for Resource Acquisition Is Initialization and is a widely accepted approach to ensure that any resource (like memory etc.) will be released properly. It is relying on the feature of having constructors and destructors for a class/structure. The following example shows this...
    Code:
    class CMemory
    {
    public:
      CMemory() { Array = new unsigned char[1000]; }
      ~CMemory() { delete [] Array; }
    
    private:
      unsigned char *Array;
    };
    As you can see, the memory will be allocated while creating the class (-> constructor) and will be automatically released while destructing the class (-> destructor). To get the bridge to the exception handling, you have to understand how exception handling works in the first place. I know that this is somehow irrelevant in regard to the original subject of the thread, however, in order to understand the interaction of RAII and exception handling it is necessary.

    C++ introduces a new mechanism to catch errors and deal with them. This mechanism is working with the keywords 'try', 'catch' und 'throw'. In simple terms this mechanism works as follows: A functions tries to process a specific piece of code. In case of an error, this function can 'throw' an exception, which can be caught by the calling procedure (-> 'catch').
    Code:
    #include <exception>
    
    void GreaterThanZero(int iValue)
    {
      if(ciValue <= 0)
        throw std::exception("Value less or equal zero")
      else
       // Do processing
    }
    
    int main()
    {
      int iInt = 0;
    
      try
      {
        GreaterThanZero(iInt);
      }
      catch(const std::exception &refcException)
      {
        // Error handling
      }
    
      return 0;
    }
    'try' starts a new area within functions can do what they want. In this case the function 'GreaterThanZero()' will throw an exception which will be caught within the 'catch' area.

    Internally the following is happen:

    1. The thrown object will be copied to a neutral position.
    2. The end of the 'try' area will be searched.
    3. If the actual function doesn't contain a 'try' area, it will be searched within the calling function.
    4. If this function still doesn't contain a 'try' area, it will be searched within the higher calling function etc. - this is called 'Unwinding the stack'
    5. During this procedure the objects within the left functions will be destroyed to avoid memory leaks.
    6. If the enclosed 'try' area is found, the first 'catch' area after the closing bracket of the 'try' area will be searched.
    7. If the thrown object the same type which is defined in the 'catch' statement, the control will be handed over to that 'catch' area otherwise the next 'catch' area will be checked.
    8. If no suitable 'catch' area is found, the next higher 'try' area will be searched.
    9. If no suitable 'catch' area is found, the application will be terminated and the exception object will be passed to the operating system.

    You can throw every kind of object, standard types like 'int', 'char', 'long' as well as structures or classes.

    'catch' areas can be react on specific objects or all exceptions:
    Code:
    catch(...)                                     // Will react on every thrown exception object
    catch(const CError &refcException)             // Will only react on thrown 'CError' and derived objects
    Objects can also be thrown within a 'catch' area to allow multiple handling routines...
    Code:
    int main()
    {
      try
      {
        Function();
      }
      catch(...)
      {
        if('I can handle this exception completely')
        {
          // Handle the exception
        }
        else
        {
          // Do, what I can do
    
          // Throw exception again
          throw();
        }
      }
    
      return 0;
    }
    The key points here are the internal points 4 and 5. In regard to classes/structures it means that during this stack unwinding the destructor of every class/structure will be callled. Now, in order to get back to the 'CMemory' class...due to the stack unwinding the destructor will be called and thus, the allocated memory will be released. If we would have no destructor supplied which explicitly releases the memory, we would have introduced a memory leak.

    To probably make it even clearer...consider the following code:
    Code:
    void func()
    {
      unsigned char *Array = new unsigned char&#091;1000&#093;;
    
      // Do some processing
    
      delete &#091;&#093; Array;
    }
    As you would agree, this is a standard way of doing it in C. At the beginning of the function memory gets allocated, at the end released. Everything is fine. Now, in the C++ world...
    Code:
    void func()
    {
      try
      {
        unsigned char *Array = new unsigned char&#091;1000&#093;;
    
        // Do some processing
    
        delete &#091;&#093; Array;
      }
      catch(const std::bad_alloc &)
      {
      }
    }
    What happens if 'Do some processing' throws an exception?

    The answer would be: We would have a memory leak. If an exception is thrown the processing of the current function is interrupted immediately and the earlier described process starts. The second step of this internal process is the search for the end of the 'try' area. Since we enclosed the whole thing with a 'try...catch' it will process the first (and the only one in this example) 'catch' statement. However, due to this, we left the scope which was determined by the 'try' block. Thus, our pointer 'Array' gets correctly deleted but not the dynamically allocated memory that pointer points to.

    Now, using the 'CMemory' class...
    Code:
    void func()
    {
      try
      {
        CMemory mem;
    
        // Do some processing
      }
      catch(const std::bad_alloc &)
      {
      }
    }
    In this case we are safe in all directions. The memory enclosed by the 'CMemory' wrapper class will always be released, either due to the destruction of the class while returning from the function regularly or due to stack unwinding in case of an exception...

    Well...this has become longer than expected...sorry for that...


    [Edited]: Fixed some language problems...
    Last edited by Andreas Masur; February 16th, 2004 at 04:59 AM.

  15. #45
    Join Date
    Feb 2003
    Location
    Brazil
    Posts
    335
    Originally posted by John E
    At least with goto, you can't jump out of the current function (you can't, can you?? I've never tried it). The problem with throw is that you can end up in a totally different function. To me, this seems to be just as unstructured - in fact, more so - than goto. So why is throw good, when goto is bad?
    The problem is with the label: the labe in a entrance for any other line of the program, the label can have more than one origen.
    The throw has a great advantage: it goes cleanning up the blocks on the scope that it is jumping on. then for exemple, the destructors of all objects created will be called, you have even the possibility on catch block to clean the memory that you allocated on try block. Almost impossible to do this with goto-label statements,
    you can end up on a totally diferent function, but on greather level of scope and with the scopes left behind cleaned. It has to be seen on scope view not on function view.

    Rabelo

Page 3 of 9 FirstFirst 123456 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured