std:string causing memory leak

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 13/05/2012 at 03:27, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   13 
Platform:      Mac OSX  ; 
Language(s) :     C++  ;

---------
Hi guys,

I'm getting a whole lot of memory leak warnings like after using std:str a number of times in a function. It seams like they are not destroyed after leaving the function, which afaik they should be.

std::string dname = bc->GetFilename(FILENAME_CACHEDIR).GetString().GetCStringCopy();

Since there is no destructor for std::str that I know of, any idea how to free the memory?

Thx,
Michael

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 13/05/2012 at 06:29, xxxxxxxx wrote:

Hi, the constructor of std::string copies the passed array internally so it doesn't take over the ownership.
You have to free the array returned by GetCStringCopy after you passed it to the constructor.

Also see: http://www.cplusplus.com/reference/string/string/string/

std::string ( const char * s );
    Content is initialized **to a copy of the string** formed...

Cheers, Sebastian

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/08/2012 at 01:49, xxxxxxxx wrote:

_> You have to free the array returned by GetCStringCopy after you passed it to the constructor.
_How are we supposed to free the array? GeFree()? Maybe I'm just blind, but I couldn't find the information in the docs.
Thanks,
Nik _
_

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/08/2012 at 02:54, xxxxxxxx wrote:

Unless you actually allocate the std::string on the heap, as shown in the example below, it will go out of scope from the stack and be freed automatically:

int MyUselessFunction()  
    
    
    {  
        // for some reason you feel the need to allocate that string on the heap  
        std::string * mystring= new std::string("Just a string.");  
        // ...  
        // deallocate it - notice that in the real world you'd use a smart pointer  
        delete mystring;  
        return 42;  
    }

What Sebastian is saying is that the C string returned by GetCStringCopy() has no owner and is only copied into the std::string.  So you will need a CHAR* to capture ownership and free the C string after assigning it to the std::string:

CHAR* cstr =  bc->GetFilename(FILENAME_CACHEDIR).GetString().GetCStringCopy();  
std::string dname = cstr;  
GeFree(cstr);

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/08/2012 at 03:23, xxxxxxxx wrote:

You can also use AutoGeFree.  
  
    Filename fname = bc->GetFilename(FILENAME_CACHEDIR);  
    AutoGeFree<const char> cstr = fname.GetString().GetCStringCopy();  
    std::string dname = cstr;  
    
or may be this way ?  
  
EDIT:  just corrected this function to work as expected.  
  
    inline void StringToSTDString(const String& str, std::string &out)
    {
        LONG len = str.GetCStringLen();
        if(len>0){
            out.reserve(len+1);
            str.GetCString(&out[0],len+1);
            out.resize(len);
        }else out.clear();
    }  
    

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/08/2012 at 03:30, xxxxxxxx wrote:

Originally posted by xxxxxxxx

What Sebastian is saying is that the C string returned by GetCStringCopy() has no owner and is only copied into the std::string.  So you will need a CHAR* to capture ownership and free the C string after assigning it to the std::string:

CHAR* cstr =  bc->GetFilename(FILENAME_CACHEDIR).GetString().GetCStringCopy();  
std::string dname = cstr;  
GeFree(cstr);

Thank you, this is what I wanted to know. 🙂

@Remotion4D:
Thank you, too.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/08/2012 at 07:13, xxxxxxxx wrote:

I think using GetCStringCopy() is not a good idea.
It use unnecessary short living memory allocation.

  
    
    
    //this one is ~5 times slower.
    inline void C4DStringToSTDStringSLOW(const String& str, std::string &out)
    {
    	if(str.Content()){
    		AutoGeFree<const char> cstr( str.GetCStringCopy() );
    		out = (cstr);
    	}else{
    		out.clear();
    	}
    }
     
    
    inline void C4DStringToSTDString(const String& str, std::string &out)
    {
    	LONG len = str.GetCStringLen();
    	if(len>0){
    		out.reserve(len+1);
    		str.GetCString(&out[0],len+1);
    		out.resize(len);
    	}else out.clear();
    }
    
    inline void STDStringToC4DString(const std::string& str,  String &out)
    {
    	LONG len = str.length();
    	if(len>0){
    		out.SetCString(&str[0],len);
    	}else{
    		out = String();
    	}
    }  
    

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 10/08/2012 at 07:32, xxxxxxxx wrote:

Well, one could simply use GetCString() and handle the CHAR* themselves (either as a heap allocation that is freed within a method or on the stack as a CHAR array).  If you are certain of the maximum length that the string might be, you can easily use CHAR cstr[MAXCSTRLEN]; in a method (where MAXCSTRLEN is some predetermined value).  In C++, the stack can be used as a sort of AutoAlloc() when the memory needed isn't too much.  Items on the stack only exist while in scope and are automatically 'freed' when they leave scope.