Thread: Can you free memory allocated by a std::string?

  1. #1
    Registered User
    Join Date
    Oct 2002
    Posts
    72

    Can you free memory allocated by a std::string?

    Say I have:

    string foo = <a string that is 1 million chars long>;

    then later I want no longer need the long foo, and would like that memory back. Is there a way to tell foo to be smaller?

    It seems that regardless of what I do, foo.capacity() remains 1 million. Surely there's a way to clear its memory, without destroying it, yes?
    Last edited by BrianK; 05-14-2008 at 06:13 PM.

  2. #2
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    whats wrong with string's resize function?

    edit: i never tested until now, and the capacity doesnt change, sorry (i guess that was too obvious)
    Last edited by nadroj; 05-14-2008 at 06:22 PM.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It seems resize didn't work to resize it back to a smaller size in my testing.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    ok this seems to be working:
    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
    	string temp = "123456789";
    
    	cout << temp.capacity() << endl;
    	temp.resize(4);
    	temp.reserve(4);
    	cout << temp.capacity() << endl;
    }
    the output is: "9 \n 4"
    if you comment one of the resize or reserve statements the capacity stays at 9, if both are in it seems to drop down to 4. maybe something weirds happening with my compiler, but give it a shot.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Only .reserve seems to produce results for me.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    i was reading the reference page for reserve and it says it wont truncate the string if the new size is less than the current size, which seems to reflect the fact that only the 'reserve' statement wouldnt change the capacity--it had to be 'resized' first. i just tried swapping the order of my statements and doing reserve then resize, but the capacity stayed at 9.

    would the inconsistency between your outcome and my outcome, elysia, be a problem with either of our compilers? im using mingw g++ 3.4.2
    Last edited by nadroj; 05-14-2008 at 06:38 PM.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I don't know. I use VS 2008.
    But I did find this on MSDN:
    Having sufficient capacity is important because reallocations is a time-consuming process and invalidates all references, pointers, and iterators that refer to characters in a string.

    The concept of capacity for objects of type strings is the same as for objects of type vector. Unlike vector, the member function reserve may be called to shrink the capacity of an object. The request is nonbinding and may or may not happen. As the default value for the parameter is zero, a call of reserve is a non-binding request to shrink the capacity of the string to fit the number of characters currently in the string. The capacity is never reduced below the current number of characters.

    Calling reserve is the only possible way to shrink the capacity of a string. However, as noted above, this request is nonbinding and may not happen.
    So .reserve can shrink the size but is not guaranteed to.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Guys, capacity is just allocated space for strings to expand.
    If you're that concerned by string's capacity, you need to swap it in or something.

    void resize ( size_t n, char c );
    void resize ( size_t n );

    resize's only job is to trim strings to n characters, or expand to n characters filling the gap with c.

    Code:
    #include <string>
    #include <iostream>
    
    int main () 
    {
        std::string lean_and_mean ( "trim the fat" );
        std::cout << "Normal: " << lean_and_mean << '\n';
        lean_and_mean.resize ( 22, '!' );
        std::cout << "Now, extatic: " << lean_and_mean << '\n';
        lean_and_mean.resize ( 4 );
        std::cout << "Finally: " << lean_and_mean << '\n';
    }
    
    // Normal: trim the fat
    // Now, extatic: trim the fat!!!!!!!!!!
    // Finally: trim

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Obviously this is not obvious due to the way they name these stupid functions.
    MSDN docs doesn't seem to shed much light into the matter either.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    > Obviously this is not obvious due to the way they name these stupid functions.

    What seems obvious to you is not my experience, unfortunately. The only reason there isn't a word about capacity is because there isn't a reason to discuss it, resize does nothing out of the ordinary. Strings manage their capacities internally.

    I would understand why you'd want a million bytes back but if the data is important, no dice.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Absolutely. If I were to allow resizing of a buffer, I would not guarantee that the class would uphold its promise to actually resize the buffer.
    But the question was if it was possible to throw away some size of the buffer... Not that I would do that, but apparently someone else do.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Oct 2002
    Posts
    72
    For the record, I have a class that holds a string. That string is a file (after it's been pre-processed - I can't simply leave the data on disk). The class holds the file as a string until it's ready to do something with it. After it does the thing, it converts the string data in some particular way & stores it elsewhere (as numbers, mainly); at which point, I no longer have use for the long string.

    If I only had to do this once, I could care less, but I have to do it a few hundred times, and keep an instance of said class around for later use. The problem is that each one of these instances is holding a 1MB string (actually, it could be quite a bit larger - I'm dealing with 500MB files today) & I may have 1-300 of the instances. This is why I need to get that memory back.

    So it appears resize & reserve are the best options; and then hope for the best. We'll see what happens. I may just convert the whole application to use dynamically allocated char*, but... that's a lot of work.

    Thanks for the pointers.

    edited to add: This is working. I know it's not a guarantee, but as of now, I'm reclaiming literally gigs of memory by calling clear() followed by reserve(). Thanks again!
    Last edited by BrianK; 05-14-2008 at 07:43 PM.

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Elysia, I guess you haven't finished reading those books...
    Chapter 82. Use the accepted idioms to really shrink capacity and really erase elements
    It's called the "swap-trick".
    Code:
    container<T>( c ).swap( c ); // the shrink-to-fit idiom to shed excess capacity
    So in the case of strings:
    Code:
    std::string( str ).swap( str ); // the shrink-to-fit idiom to shed excess capacity

  14. #14
    Banned
    Join Date
    Nov 2007
    Posts
    678
    I think your problem was (although you solved it already), how to make sure that std::string's ~destructor is called when the string is no longer needed! would not that take care of freeing the memory?

    i know only one way of invoking ~destructor, try making your std:string instance a local!

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by BrianK View Post
    Say I have:

    string foo = <a string that is 1 million chars long>;

    then later I want no longer need the long foo, and would like that memory back. Is there a way to tell foo to be smaller?

    It seems that regardless of what I do, foo.capacity() remains 1 million. Surely there's a way to clear its memory, without destroying it, yes?
    1MB isn't a whole lot in a modern machine - unless of course you have LOTS of your 1MB variables.

    My real question, however, is why you can't just destroy foo and use some other variable when you need a smaller one? That seems like the obvious solution - simpler, indeed, than messing about reserving less memory in foo.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Allocate memory inside allocated memory block?
    By Heidi_Nayak in forum C Programming
    Replies: 14
    Last Post: 04-15-2009, 04:19 PM
  2. Arrays and pointers to allocated memory
    By TriKri in forum C Programming
    Replies: 19
    Last Post: 07-23-2006, 10:52 AM
  3. Where are pointers allocated in memory?
    By sparks in forum C++ Programming
    Replies: 5
    Last Post: 07-20-2005, 12:52 PM
  4. Dynamically allocated memory
    By ^xor in forum Linux Programming
    Replies: 9
    Last Post: 06-28-2005, 11:42 AM