CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Jan 2008
    Posts
    13

    map<int,int> x; x[0]; // no valgrind warning?

    I tried this code snippet + several variations, plus
    using gcc 3.3 through 4.2, plus -00 through -03,
    and Valgrind just does not throw up an uninitialized
    variable warning:

    Code:
      #include <stdio.h>
      #include <map>
      int main() {
        std::map<int,int> x;
        printf("%d\n", x[0]);
      }
    I even pulled it up in gdb debugger, and nothing
    writes to the memory location. I even added
    x[0] = 1; at the end to verify the breakpoint worked.
    updated: I made a second try and trapped the STL
    writing 0 -- guess I botched the first attempt.


    Yet, any such access WILL be zero initially! I'm
    trying to prove that it will break to a co-worker -- but
    I'm not winning so far.

    What's going on? I don't see anything in the STL yet
    that would guarantee such behavior for POD! Thanks,
    Jason
    Last edited by xorbe; March 11th, 2008 at 04:25 AM.

  2. #2
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: map<int,int> x; x[0]; // no valgrind warning?

    The [] operator creates an entry if one doesn't already exist.

    To do a lookup that can't create an entry which isn't there, you have to use find().

  3. #3
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    (The example stands precisely as presented. I know
    what I'm talking about here.)

    Well I'll be, it is initialized by the STL!
    Is this guaranteed by the STL spec somewhere?

    stl_construct.h
    Code:
      /**
       * @if maint
       * Constructs an object in existing memory by invoking an allocated
       * object's constructor with an initializer.
       * @endif
       */
      template <class _T1, class _T2>
        inline void
        _Construct(_T1* __p, const _T2& __value)
        { new (static_cast<void*>(__p)) _T1(__value); }
    I constructed a better test, and the debugger stopped at
    that point as being written by the STL.

    stl_tree.h
    Code:
          _Link_type
          _M_create_node(const value_type& __x)
          {
    	_Link_type __tmp = _M_get_node();
    	try 
    	  { _Construct(&__tmp->_M_value_field, __x); } // here
    	catch(...)
    	  {
    	  _M_put_node(__tmp);
    	  __throw_exception_again; 
    	  }
    	return __tmp;
          }
    Last edited by xorbe; March 10th, 2008 at 06:14 PM.

  4. #4
    Join Date
    Feb 2003
    Posts
    377

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Quote Originally Posted by xorbe
    Well I'll be, it is initialized by the STL!
    Is this guaranteed by the STL spec somewhere?
    Yes. According to the C++ standard, an entry will be added with that key and a value-initialized value (which basically default constructs class types and zero-initializes built-in types).
    Last edited by jlou; March 10th, 2008 at 06:16 PM.

  5. #5
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Quote Originally Posted by jlou
    Yes. According to the C++ standard, an entry will be added with that key and a default-initialized value.
    But what [value]-initialized value? Does it say "zero"?

    I know if you have a map of
    Code:
    struct foo {
      foo(){}
      int x;
    }
    you will get garbage, because it is non-POD.
    Last edited by xorbe; March 11th, 2008 at 12:40 PM.

  6. #6
    Join Date
    Feb 2003
    Posts
    377

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Sorry, yes. If the value type is int, then the new value will be 0. If the value type is foo above, then the default constructor for foo will be called, which does not initialize x.

    It basically calls T() for the value type T.

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Quote Originally Posted by xorbe
    (The example stands precisely as presented. I know
    what I'm talking about here.)

    Well I'll be, it is initialized by the STL!
    Is this guaranteed by the STL spec somewhere?
    It isn't just the spec. The map has no choice but to create a new member for operator [].

    When you do something like this:
    Code:
    x[0] = 10;
    There are two operations going on, not one. First the key is created using operator []. The second operation is the call of the assignment operator. But look at the first thing that's done -- a key is created. This is done regardless of whether there is an assignment being done or not. There is no way for the map's operator [] to anticipate that you're using [] for key creation or just as an accessor.

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Quote Originally Posted by Paul McKenzie
    There are two operations going on, not one. First the key is created using operator []. The second operation is the call of the assignment operator. But look at the first thing that's done -- a key is created. This is done regardless of whether there is an assignment being done or not. There is no way for the map's operator [] to anticipate that you're using [] for key creation or just as an accessor.

    Regards,

    Paul McKenzie
    Yes, I know all that. You're missing my (er, intended) question here. I have traced the question down to this line of code in the STL:

    Code:
    __i = insert(__i, value_type(__k, mapped_type()));
    mapped_type is _Tp which is int.

    So, my ultimate question is,
    why is "int()" guaranteed to be zero?
    Where can I read this guarantee?

    Will "bool()" always be false?

    Will "type*()" always be NULL?

    Thanks,
    Jason
    Last edited by xorbe; March 10th, 2008 at 06:28 PM.

  9. #9
    Join Date
    Feb 2003
    Posts
    377

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Quote Originally Posted by xorbe
    So, my ultimate question is,
    why is "int()" guaranteed to be zero?
    Where can I read this guarantee?

    Will "bool()" always be false?

    Will "type*()" always be NULL?

    Thanks,
    Jason
    Yes.

    Section 8.5 of the C++ standard. Paragraph 7 states:
    An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
    Paragraph 5 above it clarifies what value-initialized means:
    To zero-initialize an object of type T means:
    if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
    — if T is a non-union class type, each nonstatic data member and each base-class subobject is zeroinitialized;
    — if T is a union type, the object’s first named data member89) is zero-initialized;
    — if T is an array type, each element is zero-initialized;
    — if T is a reference type, no initialization is performed.

    To default-initialize an object of type T means:
    — if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is
    ill-formed if T has no accessible default constructor);
    — if T is an array type, each element is default-initialized;
    — otherwise, the object is zero-initialized.

    To value-initialize an object of type T means:
    — if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is
    called (and the initialization is ill-formed if T has no accessible default constructor);
    — if T is a non-union class type without a user-declared constructor, then every non-static data member
    and base-class component of T is value-initialized;
    — if T is an array type, then each element is value-initialized;
    otherwise, the object is zero-initialized
    I added bold emphasis to indicate what I think are the applicable sections.
    Last edited by jlou; March 10th, 2008 at 06:35 PM.

  10. #10
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    That's awesome, many thanks!

  11. #11
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    As a follow-up question, what about:

    Code:
    struct foo {
      int x;
      int y;
    };
    So then, foo() implies int() inside due to a lack of a constructor?

    foo x; // will the values be zero?
    foo y = foo(); // what about here?

    (Er, I guess I can use Valgrind again to determine this... sigh...)
    Last edited by xorbe; March 10th, 2008 at 07:01 PM.

  12. #12
    Join Date
    Feb 2003
    Posts
    377

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Since there is no user declared constructor, then I would imagine x and y are set to 0 when an instance of foo is value initialized. However, if an instance of foo is default initialized, then x and y will have undefined values.

    Your second example will value-initialize y, but I'm not sure about the first. I believe in non-global scope it will default-initialize (and therefore leave the x and y members uninitialized).

  13. #13
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    I read that even global scope, bss can be non-zero given the right gcc flags... (but you have to be aiming for that)

  14. #14
    Join Date
    Feb 2003
    Posts
    377

    Re: map<int,int> x; x[0]; // no valgrind warning?

    You can do lots of non-standard things with the right compiler options set.

  15. #15
    Join Date
    Jan 2008
    Posts
    13

    Re: map<int,int> x; x[0]; // no valgrind warning?

    Yeah, foo x; is uninitialized (as expected), and foo y = foo(); is initialized, according to Valgrind. Wow I feel silly... huh.
    Last edited by xorbe; March 11th, 2008 at 04:27 AM.

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