The 20 lines of shame

April 5, 2009 · Posted in C / C + + , Opinion

While rice is cooking, I remembered a curious case that happened to me early in his career, involving memory management in C + +. At that time I was much more. Younger, faster, more arrogant and more newbie ...

A more experienced co-worker was explaining to another less experienced colleague that for every new there must be a corresponding delete. Otherwise the object will persist in memory and there may be memory leaks.

At this point I interrupted him and said "not necessarily because it is sufficient that the object out of scope so the destructor is automatically called.."

Since then rolled a 10 min debate with arguments and counter arguments, and the whole team still watching. In the end, half the team agreed with him and the other half with me, and at that point nobody had in mind a way to check to see. Look on the Internet was not an option.

As I had all the answers, after all already programmed in PHP, Java and C + + was to show later that I was right.

Days later, one of those philosophical moments, I remembered that a memory address is a number, and you can either convert an address to a common number, and go the other way, although the latter is usually useless.

Then I devised a way to prove my theory: It would create an object in a scope restricted to allocating new. Save the address of this object as a common number in a long out of the restricted scope, expect to finalize the restricted scope, the destructor of obejto be called and then the outer scope, use the number representing the address of the object to access that area of memory showing that receive a SIGSEGV (segmentation fault) by trying to access an invalid memory area. Then I generated the code below.

  A
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
  # Include
 # Include <string>

 using namespace std;

 int argc, char ** argv ) { int main (int argc, char ** argv) {
     0 ; unsigned long a = 0;

     {
         new string ( "Hello World!!!" ) ; * str = new String ("Hello World!");
         unsigned long ) str ; a = (unsigned long) str;

         "str: " << str << endl ; court <<"str:" <<str <<endl;
         "num: " << num << endl ; court <<"num:" <<a <<endl;
     }

     * ( ( string * ) num ) << endl ; court <<* ((* ​​string) a) <<endl;

     ; return 0;
 } 

Behold, to my surprise the program did not explode in my face. He worked correctly pointing out that in fact I was the one who was wrong.

Searching more I realized that yes, there should be new for each one and only delete, and more for each new [] must be one and only one delete []. What I thought I knew about memory management and scope, it was probably some confusion between different languages.

When I started the discussion day before, I made all the basic mistakes that a newbie commits:

  1. Meddle where it was called.
  2. Swearing standing by what is right without evidence.
  3. Underestimate the knowledge of someone more experienced.
  4. Think you have all the answers just because they just see it in class.
  5. To think that just because they know the basics of several languages, then you have all the answers.

Like any good member of the species Homo sapiens , talked shit. My reaction to this discovery was to take the whole team and I was wrong, apologize for speaking nonsense and show these twenty lines of code used to demonstrate this. Moreover, I showed all sources I have checked and even brought out other details about memory management that we were escaping, like circular references . This led to a re-desing of some parts of the project.

My 20 lines cógigo became known as "The 20 lines of shame" and natual so I was screwed. Every time anyone had any doubts spoke "there is 20 lines of vegonha for testing." The meaning was something like "there is a simple test to not be embarrassed later."

The most important thing is that my post-shit attitude was well received and brought benefits to the team. If I had shied away sooner or later someone would prove I was wrong in front of everyone, or worse, behind the scenes. Admit mistakes and learn from it showed that I was prepared to be challenged. In addition to this team showed that the more I seemed arrogant (I look like more than I am ...), I knew it was an ordinary human who made mistakes like everyone else, I do not think more than anyone. This paved the way for other team members feel free to do the same and we become a more cohesive team.

Comments

  • Marcus Antonius

    Very interesting story!
    More luggage for those who followed the debate!

    Another interesting thing is the lack of 18 days for the new release of Ubuntu!
    (But it ?????????? Time flies!)

  • http://blabos.org blab

    Lately for me time're not flying, teleportation goin ...

  • Junio

    Blaber, thank you for passing experience. Very rich text. Peace and health to you.

  • ♣ ♦ ♥ ♠ Hime Cheshire

    Hmm ... I'm not sure what compiler you use or what version of the language, but I know, C does not display errors when accessing deallocated memory unless it is protected by the operating system ... The C + + displays?

  • Blaber http://blabos.org of bleb

    First thanks for visiting!

    It is C + + with g + +, small padawan :)

    It depends on what you consider "display errors".

    At compile time or runtime?

    In the above case, inexperience expected (cacophonous this!) Destruction automatic output scope (which does not exist for an object dynamically allocated in C + +), followed by derreferenciação a pointer pointing to an area (previously) deallocated memory , causing a fatal error at runtime.

    Add a delete str; after line 14 you'll notice the subtle difference.

    Both tests do not give no warning at compile time.

  • ♣ ♦ ♥ ♠ Hime Cheshire

    No no, I speak in the same runtime ... At first when I was learning to program, our teacher taught us vectors before alloc, malloc and calloc, and thus, we used vectors freely without allocating memory ...

    Rarely gave an error of memory-protected operating system ...
    Moreover, any error did not appear, or the compilation or execution.

    Of course it was not with objects, it was only with C, in the classes of structured programming ... So my question ... In C + +, using new instead of alloc, the program generates errors at runtime if I try to use a memory not allocated?

    I think it would be nice to see the specifications of the language, after all, the destructor, and deallocate memory, you can protect it until the completion of the program or something ... or it does not happen?

  • Blaber http://blabos.org of bleb

    The term "vector we used freely without allocating memory" is quite misleading, for memory arrays need to exist. Probably you mean "we used freely without vectors dynamically allocate memory."

    The specification says derreferenciar a null pointer results in undefined behavior, which in most systems (but not all) means a fatal error.

    This is not what is shown above. In the example there is an attempt to access an area "allegedly" deallocated.

    Null pointer! = Pointer to invalid memory area.


    int* ptr_null = 0;

    / / Is a null pointer ptr_null

    ptr_foo = new int * int (123456);
    delete ptr_foo;

    / / Ptr_foo points to a memory area
    / / That no longer belongs to this program

    printf ("% pn", ptr_null);
    printf ("% pn", ptr_foo);

    Compile and run the examples you will see the difference.

    Regarding the last paragraph, no, that's not what happens. You are mixing things up, the destructor is just a routine that is called automatically when an object is deallocated, either by a call to delete dynamically allocated objects on output or scope of objects allocated on the heap.

blog comments powered by Disqus