string/stringstream memory management

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

    string/stringstream memory management

    Im sorry for asking a question that is surely in the archives somewhere, but
    I have been unable to locate it.

    Its about string memory management. I need to dynamically construct a
    C-style string and was planning to go about it this way;

    char* foo()
    {
    std::stringstre am ss;
    ss << ...
    std::string s = ss.str();
    char* c = s.c_str();
    return c;
    }

    void main()
    {
    char* c = foo();
    // work with c
    delete(c);
    }

    What am I doing wrong? Should I be deleting stuff somewhere? Will the foo
    return a pointer to some out of scope memory - should it be;

    char* foo()
    {
    std::stringstre am* ss = new std::stringstre am();
    *ss << ...
    std::string s = ss->str();
    delete(ss);
    char* c = s.c_str();
    return c;
    }

    Am I deleting too much? ...

    Thanks for any guidance you can offer.

    El.
  • Gianni Mariani

    #2
    Re: string/stringstream memory management

    Ellarco wrote:[color=blue]
    > Im sorry for asking a question that is surely in the archives somewhere, but
    > I have been unable to locate it.[/color]

    This one is a classic -
    [color=blue]
    >
    > Its about string memory management. I need to dynamically construct a
    > C-style string and was planning to go about it this way;[/color]

    That usually means use of new
    [color=blue]
    >
    > char* foo()
    > {
    > std::stringstre am ss;[/color]
    ^^^^ defined automatic - life of object is life of function[color=blue]
    > ss << ...
    > std::string s = ss.str();[/color]
    ^^^^ defined automatic - life of object is life of function[color=blue]
    > char* c = s.c_str();[/color]
    ^^^^ s.c_str() did not copy or allocate new memory for this[color=blue]
    > return c;[/color]
    ^^^^ Oops - returning a pointer to memory that is just about to be
    deleted ...
    [color=blue]
    > }
    >
    > void main()
    > {
    > char* c = foo();[/color]
    ^^^^ c is pointing to memory that is unallocated[color=blue]
    > // work with c
    > delete(c);[/color]
    ^^^^ trying to deallocate a pointer that is not allocated bad bad bad[color=blue]
    > }
    >
    > What am I doing wrong? Should I be deleting stuff somewhere? Will the foo
    > return a pointer to some out of scope memory - should it be;
    >
    > char* foo()
    > {
    > std::stringstre am* ss = new std::stringstre am();
    > *ss << ...
    > std::string s = ss->str();
    > delete(ss);[/color]
    ^^^^ It's not your responsibility to delete this, s will do it when it
    gets destroyed.[color=blue]
    > char* c = s.c_str();
    > return c;
    > }
    >
    > Am I deleting too much? ...[/color]

    YEP.

    [color=blue]
    >
    > Thanks for any guidance you can offer.
    >
    > El.[/color]

    Comment

    • Ron Natalie

      #3
      Re: string/stringstream memory management


      "Ellarco" <nobrow@eircom. net> wrote in message news:5569fec9.0 309240619.8a0c2 3b@posting.goog le.com...

      [color=blue]
      > char* c = s.c_str();[/color]

      First, this shouldn't even compile. c_str() is returns const char*.

      The return value of c_str() becomes invalid as soon as a non-const member
      (including the destructor), get's invoked. S is destroyed as soon as the
      function exits so the value returned is invalid by the time it reaches the
      caller.

      You could return a copy.
      char* c = new char[s.size()+1];
      strcpy(c, s.c_str());
      return c;
      [color=blue]
      > void main()[/color]

      main must return int.
      [color=blue]
      > delete(c);[/color]

      Delete is not a function. You don't need the parens. Further,
      Since your intent is that c points to an array allocation, the proper
      delete is:
      delete [] c;
      [color=blue]
      > std::stringstre am* ss = new std::stringstre am();
      > *ss << ...
      > std::string s = ss->str();
      > delete(ss);[/color]

      This is just an elaborate way of doing the same thing you had before.
      It's not the stringstream that was the problem, it was what you did with
      the string called "s" afterwoard.

      Why not just return a string. It's usually easier when you need a const char*
      out of a string to just use c_str() at the last possible moment. Frequently, the
      lifetime of ths string is such that you don't have to wory about making a copy
      of the c_str() value because your string persists longer than the char* is needed.


      Comment

      • Frank Schmitt

        #4
        Re: string/stringstream memory management

        nobrow@eircom.n et (Ellarco) writes:
        [color=blue]
        > Im sorry for asking a question that is surely in the archives somewhere, but
        > I have been unable to locate it.
        >
        > Its about string memory management. I need to dynamically construct a
        > C-style string and was planning to go about it this way;
        >
        > char* foo()
        > {
        > std::stringstre am ss;[/color]

        use std::ostringstr eam
        [color=blue]
        > ss << ...
        > std::string s = ss.str();
        > char* c = s.c_str();
        > return c;
        > }[/color]

        here, s goes out of scope and is destroyed - c points to never-neverland.
        [color=blue]
        > void main()[/color]

        main returns int
        [color=blue]
        > {
        > char* c = foo();
        > // work with c
        > delete(c);
        > }[/color]

        You can either create a new C-style string in foo() using strcpy(), or
        you can (much preferable IMHO) just return a std::string from foo:

        std::string foo() {
        std::ostringstr eam ss;
        ss << ...;
        return ss.str();
        }

        If you insist on using C-style strings, create one with new[] in
        foo, strcpy() to it, and delete[] it in main().

        HTH & kind regards
        frank

        --
        Frank Schmitt
        4SC AG phone: +49 89 700763-0
        e-mail: frankNO DOT SPAMschmitt AT 4sc DOT com

        Comment

        • Karl Heinz Buchegger

          #5
          Re: string/stringstream memory management



          Ellarco wrote:[color=blue]
          >
          > Im sorry for asking a question that is surely in the archives somewhere, but
          > I have been unable to locate it.
          >
          > Its about string memory management. I need to dynamically construct a
          > C-style string and was planning to go about it this way;
          >
          > char* foo()
          > {
          > std::stringstre am ss;
          > ss << ...
          > std::string s = ss.str();
          > char* c = s.c_str();
          > return c;
          > }
          >[/color]

          Bad idea.
          AT the moment this function terminates, the object s is killed.
          And since the object s is killed, so is the buffer it handed out
          to you through c_str().

          [color=blue]
          > void main()[/color]

          int main()
          [color=blue]
          > {
          > char* c = foo();
          > // work with c
          > delete(c);[/color]

          wrong syntax. Must be delete [] c;
          Please: always cut and paste code, don't write it directly in your
          newsreader. Otherwise we are hunting bugs which simply are not there
          in your real program.

          Well. Did you allocate something? Did your documentation of c_str()
          tell you to delete the buffer?
          The answer is no in both cases. So, no, you don't have to delete
          anything (but that will change in a short while :-)

          As you have seen, you can't return what c_str() gives to you, since
          the object itself goes out of scope and hence the buffer is deleted,
          while doing so. From this it follows that you first have to create
          a copy of the C-style string:

          char* foo()
          {
          ....
          std::string s = ss.str();

          char* c = new char [ s.size() + 1 ];
          strcpy( c, s.c_str() );
          return c;
          }

          Now foo hands out a dynamically allocated buffer which is filled with
          a copy of what c_str() handed out.
          And since this buffer was allocated with new[], you have to delete[]
          it somewhere.

          int main()
          {
          char* cc = foo();
          ....
          delete [] c;
          }

          --
          Karl Heinz Buchegger
          kbuchegg@gascad .at

          Comment

          • Ellarco

            #6
            Re: string/stringstream memory management


            "Karl Heinz Buchegger" <kbuchegg@gasca d.at> wrote in message
            news:3F71B5EA.9 F270775@gascad. at...[color=blue]
            >
            >
            > Ellarco wrote:[color=green]
            > >
            > > Im sorry for asking a question that is surely in the archives somewhere,[/color][/color]
            but[color=blue][color=green]
            > > I have been unable to locate it.
            > >
            > > Its about string memory management. I need to dynamically construct a
            > > C-style string and was planning to go about it this way;
            > >
            > > char* foo()
            > > {
            > > std::stringstre am ss;
            > > ss << ...
            > > std::string s = ss.str();
            > > char* c = s.c_str();
            > > return c;
            > > }
            > >[/color]
            >
            > Bad idea.
            > AT the moment this function terminates, the object s is killed.
            > And since the object s is killed, so is the buffer it handed out
            > to you through c_str().
            >
            >[color=green]
            > > void main()[/color]
            >
            > int main()
            >[color=green]
            > > {
            > > char* c = foo();
            > > // work with c
            > > delete(c);[/color]
            >
            > wrong syntax. Must be delete [] c;
            > Please: always cut and paste code, don't write it directly in your
            > newsreader. Otherwise we are hunting bugs which simply are not there
            > in your real program.
            >
            > Well. Did you allocate something? Did your documentation of c_str()
            > tell you to delete the buffer?
            > The answer is no in both cases. So, no, you don't have to delete
            > anything (but that will change in a short while :-)
            >
            > As you have seen, you can't return what c_str() gives to you, since
            > the object itself goes out of scope and hence the buffer is deleted,
            > while doing so. From this it follows that you first have to create
            > a copy of the C-style string:
            >
            > char* foo()
            > {
            > ....
            > std::string s = ss.str();
            >
            > char* c = new char [ s.size() + 1 ];
            > strcpy( c, s.c_str() );
            > return c;
            > }
            >
            > Now foo hands out a dynamically allocated buffer which is filled with
            > a copy of what c_str() handed out.
            > And since this buffer was allocated with new[], you have to delete[]
            > it somewhere.
            >
            > int main()
            > {
            > char* cc = foo();
            > ....
            > delete [] c;
            > }
            >
            > --
            > Karl Heinz Buchegger
            > kbuchegg@gascad .at[/color]

            Thanks to all. Youve cleared it up. To summarise what youve said, everything
            is as normal. I had an idea in my head that string behaved in some sort of
            anomalas (in terms of memory) way - idiot. Apologies for the buggy code I
            posted, and thanks again.

            El.


            Comment

            Working...