I am mystified... need help with STL.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ben Thomas

    I am mystified... need help with STL.

    Hi all,

    I'm having some trouble understanding the behavior of std::ostringstr eam.
    (I'm using Visual Studio .Net & STL port 4.5.3). I'll appreciate if someone
    can give me a little explanation of this behavior and how it is possible...

    Here's my code

    //////////////////////////
    #include <stdio.h>
    #include <ostream>

    void func( const char* s )
    {
    printf( "func: [%u], [%s]\n", s, s );
    }

    void main( void )
    {
    std::ostringstr eam stream;
    stream << "Hello World";
    const char* s = stream.str().c_ str();
    printf( "main: [%u], [%s]\n", s, s );
    func( stream.str().c_ str() );
    }
    ////////////////////////////////

    And here's my result:

    main: [3290280], []
    func: [3290280], [Hello World]

    Thankx a lot!
    Ben Thomas.


  • Kevin Goodsell

    #2
    Re: I am mystified... need help with STL.

    Ben Thomas wrote:
    [color=blue]
    > Hi all,
    >
    > I'm having some trouble understanding the behavior of std::ostringstr eam.
    > (I'm using Visual Studio .Net & STL port 4.5.3). I'll appreciate if someone
    > can give me a little explanation of this behavior and how it is possible...
    >
    > Here's my code
    >
    > //////////////////////////
    > #include <stdio.h>
    > #include <ostream>[/color]

    What about <sstream>?
    [color=blue]
    >
    > void func( const char* s )
    > {
    > printf( "func: [%u], [%s]\n", s, s );[/color]

    This invokes undefined behavior. The %u format specifier is for unsigned
    ints only. You are passing it a const char *. This is a good example of
    why you should not use printf or any function or language construct that
    defeats type-checking.
    [color=blue]
    > }
    >
    > void main( void )[/color]

    main returns int. void is not and never has been an acceptable return
    type for main.
    [color=blue]
    > {
    > std::ostringstr eam stream;
    > stream << "Hello World";
    > const char* s = stream.str().c_ str();[/color]

    My best guess is that ostringstream:: str() returns by value (strangely,
    I can't find this information in either Stroustrup or Josuttis). That
    means you get a temporary std::string, which you then invoke c_str() on.
    However, the temporary goes out of scope after this statement completes,
    and the pointer returned from c_str() is no longer valid. Try this instead:

    std::string tmp = stream.str();
    const char* s = tmp.c_str();
    [color=blue]
    > printf( "main: [%u], [%s]\n", s, s );[/color]

    Undefined behavior again.
    [color=blue]
    > func( stream.str().c_ str() );[/color]

    In this case, the same thing happens except that the temporary does not
    go out of scope until the function completes.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.

    Comment

    • Ron Natalie

      #3
      Re: I am mystified... need help with STL.


      "Kevin Goodsell" <usenet1.spamfr ee.fusion@never box.com> wrote in message news:AA68b.8848[color=blue][color=green]
      > > printf( "func: [%u], [%s]\n", s, s );[/color]
      >
      > This invokes undefined behavior. The %u format specifier is for unsigned
      > ints only. You are passing it a const char *. This is a good example of
      > why you should not use printf or any function or language construct that
      > defeats type-checking.[/color]

      Yes, if he wants to inspect the pointer, the way to do it is:
      printf("func [%p],[%s]\n", (void*)s, s);



      Comment

      • Unforgiven

        #4
        Re: I am mystified... need help with STL.

        Ron Natalie wrote:[color=blue]
        > "Kevin Goodsell" <usenet1.spamfr ee.fusion@never box.com> wrote in
        > message news:AA68b.8848[color=green][color=darkred]
        >>> printf( "func: [%u], [%s]\n", s, s );[/color]
        >>
        >> This invokes undefined behavior. The %u format specifier is for
        >> unsigned ints only. You are passing it a const char *. This is a
        >> good example of why you should not use printf or any function or
        >> language construct that defeats type-checking.[/color]
        >
        > Yes, if he wants to inspect the pointer, the way to do it is:
        > printf("func [%p],[%s]\n", (void*)s, s);[/color]

        To be a complete nitpicker, the C++ way to do it is:
        std::cout << "main: [" << static_cast<con st void*>(s) << "], [" << s <<
        "]" << std::endl;

        Or even more nitpicky, we should forget char* altogether, std::string should
        be good enough for us C++ types:
        std::cout << "main: [" << stream.str() << "]" << std::endl;

        ^_^

        --
        Unforgiven

        "Most people make generalisations "
        Freek de Jonge

        Comment

        • Ben Thomas

          #5
          Re: I am mystified... need help with STL.

          Thankx for the answer!

          Okay, I have fixed the problem with displaying the pointers value and change
          #include<ostrea m> with #include<sstrea m> and return 0 in the main function
          and it's the same behavior! :)

          The solution of a temp variable works! I too first though that it was a
          scope problem, that's why I displayed the pointer value. Yet, they are the
          same, so scope seems to be okay, only that it's empty in one call and not in
          the other. Also, I don't know if there's a difference in scope between the
          two kind of call... I have tryed to write a class that reproduce the same
          kind of behavior but wasn't able to do so... maybe it's in the many level of
          template with STL, but how can you make your class act differently between
          this

          const char* s = stream.str().c_ str();

          and this

          func( stream.str().c_ str() ); // void func( const char* s );

          I just can't make sense of it... maybe the problem is elsewhere after all.
          Ben Thomas.

          "Ron Natalie" <ron@sensor.com > wrote in message
          news:3f60f744$0 $51786$9a6e19ea @news.newshosti ng.com...[color=blue]
          >
          > "Kevin Goodsell" <usenet1.spamfr ee.fusion@never box.com> wrote in message[/color]
          news:AA68b.8848[color=blue][color=green][color=darkred]
          > > > printf( "func: [%u], [%s]\n", s, s );[/color]
          > >
          > > This invokes undefined behavior. The %u format specifier is for unsigned
          > > ints only. You are passing it a const char *. This is a good example of
          > > why you should not use printf or any function or language construct that
          > > defeats type-checking.[/color]
          >
          > Yes, if he wants to inspect the pointer, the way to do it is:
          > printf("func [%p],[%s]\n", (void*)s, s);
          >
          >
          >[/color]


          Comment

          • Kevin Goodsell

            #6
            Re: I am mystified... need help with STL.

            Ben Thomas wrote:
            [color=blue]
            > Thankx for the answer![/color]

            Please don't top-post. Re-read section 5 of the FAQ for posting guidelines.


            [color=blue]
            >
            > Okay, I have fixed the problem with displaying the pointers value and change
            > #include<ostrea m> with #include<sstrea m> and return 0 in the main function
            > and it's the same behavior! :)
            >
            > The solution of a temp variable works! I too first though that it was a
            > scope problem, that's why I displayed the pointer value. Yet, they are the
            > same,[/color]

            This proves absolutely nothing.
            [color=blue]
            > so scope seems to be okay,[/color]

            Bad conclusion.
            [color=blue]
            > only that it's empty in one call and not in
            > the other.[/color]

            It's undefined in one call, and not in the other.
            [color=blue]
            > Also, I don't know if there's a difference in scope between the
            > two kind of call... I have tryed to write a class that reproduce the same
            > kind of behavior but wasn't able to do so... maybe it's in the many level of
            > template with STL, but how can you make your class act differently between
            > this
            >
            > const char* s = stream.str().c_ str();[/color]

            OK, I'll try to explain again (but I suspect you need to look up
            "temporarie s" or "temporary objects" in your C++ book).

            stream.str() returns by value. This means that the result is copied into
            a "temporary object". Now, the ruled for temporary objects state that
            they go out of scope at the end of the full expression in which they are
            created. A full expression is an expression that is not a sub-expression
            of any larger expression, therefore the full expression in this
            particular case is the entire statement, minus the semi-colon. That
            means that the temporary std::string object containing the result of
            stream::str() is GONE once this statement completes. It no longer exists.

            Since the pointer returned from std::string::c_ str() ceases to be valid
            when the std::string is modified or destroyed, your 's' pointer stops
            being valid as soon as you initialize it.
            [color=blue]
            >
            > and this
            >
            > func( stream.str().c_ str() ); // void func( const char* s );[/color]

            In this case, the full expression includes the function call. The
            function call uses the pointer while it's still valid. As soon as the
            function completes, the temporary std::string object goes out of scope
            and the pointer is no longer valid - but that's OK this time because you
            haven't saved it anywhere.
            [color=blue]
            >
            > I just can't make sense of it... maybe the problem is elsewhere after all.[/color]

            I'm quite sure this IS the problem. I've verified my assumption about
            the return type of std::ostringstr eam::str() by checking the standard.
            What you are doing is roughly equivalent to this:

            #include <iostream>
            #include <cstring>

            using namespace std;

            class Stupid
            {
            char *str;
            public:
            Stupid() : str(new char[20]) { strcpy(str, "this is stupid");
            cout << "Constructi ng a Stupid object" << endl; }
            ~Stupid() { delete [] str;
            cout << "Destroying a Stupid object"
            " (and releasing memory)" << endl; }
            char *GetPtr() { return str; }
            };

            int main()
            {
            char *s = Stupid().GetPtr ();

            cout << "The string pointed to by s is:\n" << s << endl;

            return 0;
            }

            If you can't see why this is horribly broken, try running it. The object
            dies and releases its memory before you even have a chance to use 's'.

            -Kevin
            --
            My email address is valid, but changes periodically.
            To contact me please use the address from a recent posting.

            Comment

            • Peter Kragh

              #7
              Re: I am mystified... need help with STL.

              So, Ben, if you really want your code to work, just make a few adjustments:

              #include <stdio.h>
              #include <sstream>
              #include <string>

              void func( const char* s )
              {
              printf( "func: [%p], [%s]\n", s, s );
              }

              void main( void )
              {
              std::ostringstr eam stream;
              stream << "Hello World";
              std::string s = stream.str();
              printf( "main: [%p], [%s]\n", s.c_str(), s.c_str() );
              func( stream.str().c_ str() );
              }

              That way, you *copy* the temporary object to a new (non-temporary) one, and
              it's valid when you call your func function.

              Maybe this should help you understand std::ostringstr eam a little better :-)

              BR,
              Peter Kragh


              Comment

              • Kevin Goodsell

                #8
                Re: I am mystified... need help with STL.

                Peter Kragh wrote:[color=blue]
                > So, Ben, if you really want your code to work, just make a few adjustments:
                >
                > #include <stdio.h>[/color]

                Deprecated.
                [color=blue]
                > #include <sstream>
                > #include <string>
                >
                > void func( const char* s )
                > {
                > printf( "func: [%p], [%s]\n", s, s );[/color]

                This is an error, as has already been discussed in this thread. %p only
                accepts void*.
                [color=blue]
                > }
                >
                > void main( void )[/color]

                main must return int. This is required by the C++ standard.
                [color=blue]
                > {
                > std::ostringstr eam stream;
                > stream << "Hello World";
                > std::string s = stream.str();
                > printf( "main: [%p], [%s]\n", s.c_str(), s.c_str() );[/color]

                Same error.
                [color=blue]
                > func( stream.str().c_ str() );
                > }
                >
                > That way, you *copy* the temporary object to a new (non-temporary) one, and
                > it's valid when you call your func function.
                >
                > Maybe this should help you understand std::ostringstr eam a little better :-)
                >[/color]

                -Kevin
                --
                My email address is valid, but changes periodically.
                To contact me please use the address from a recent posting.

                Comment

                Working...