CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Aug 2002
    Posts
    756

    [SOLVED]: Memory leaks detected

    Hi, ALL,
    Code:
    struct DataEditFiield
    {
        int type, m_size, m_precision;
        union ValuueType
        {
            void *blobValue;
            int intValue;
            double doubleValue;
            std::wstring stringValue;
            ValuueType() : intValue( 0 ), doubleValue( 0.0 ), stringValue( L"" )  {}
            ValuueType(int value) : intValue( value ) {}
            ValuueType(double value) : doubleValue( value ) {}
            ValuueType(std::wstring value) : stringValue( value ) {}
            ValuueType(const void *value) : blobValue( const_cast<void *>( value ) ) {}
            ValuueType(const ValuueType &myvalue)
            {
                stringValue = myvalue.stringValue;
                intValue = myvalue.intValue;
                doubleValue = myvalue.doubleValue;
                blobValue = myvalue.blobValue;
                longvalue = myvalue.longvalue;
            }
    #if defined _MSC_VER
            __int64 longvalue;
            ValuueType(__int64 value) : longvalue( value ) {}
    #else
    		long long int longvalue;
    		ValuueType(long long int value) : longvalue( value ) {}
    #endif
            ~ValuueType() noexcept {}
        } value;
    
        DataEditFiield(int myvalue) : type( INTEGER_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) { }
    
        DataEditFiield(double myvalue, int size, int precision) : type( DOUBLE_TYPE ), m_size( size ), m_precision( precision ), value( myvalue ) { }
    
        DataEditFiield(std::wstring myvalue) : type( STRING_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) {}
    
        DataEditFiield(const void *myvalue) : type( BLOB_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) {}
    
    #if defined _MSC_VER
        DataEditFiield(__int64 myvalue) : type( INTEGER_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) {}
    #else
    	DataEditFiield(long long int myvalue) : type( 1 ), value( myvalue ) {}
    #endif
    
        DataEditFiield(const DataEditFiield &field)
        {
            switch( field.type )
            {
            case INTEGER_TYPE:
                value.intValue = field.value.intValue;
                break;
            case DOUBLE_TYPE:
                value.doubleValue = field.value.doubleValue;
                break;
            case STRING_TYPE:
                value.stringValue = field.value.stringValue;
                break;
            case BLOB_TYPE:
                value.blobValue = field.value.blobValue;
                break;
            }
            type = field.type;
            m_size = field.m_size;
            m_precision = field.m_precision;
        }
    
        ~DataEditFiield()
        {
            using std::wstring;
            if( type ==3 )
                value.stringValue.~wstring();
        }
    };
    Then somewhere in the cpp code:

    Code:
    std::vector<DataEditFiield> vec;
    vec.push_back( 1, 1 );
    reports memory leak by VLD and MSVC in:

    ValuueType() : intValue( 0 ), doubleValue( 0.0 ), stringValue( L"" ) {}

    from

    DataEditFiield(const DataEditFiield &field)

    My questions are:

    Where is the pointer created and how to get rid f the leak?

    Using C++11 (not 17).

    Thank you.
    Last edited by OneEyeMan; March 28th, 2021 at 11:41 PM.

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Memory leaks detected

    Are you sure that ValuueType should be a union and not a struct? A union is a special class type that can hold only one of its non-static data members at a time. but in the constructor for ValuueType you are tying to initialise 3 of it's 4 members together???? You should only initialise the active union member. If a union has one member which is a class, then when referencing another member, the destructor should be called first. eg

    Code:
    #include <iostream>
    #include <string>
    #include <vector>
     
    union S
    {
        std::string str;
        std::vector<int> vec;
        ~S() {} // Will call destructor for the current active member
    };          // the whole union occupies max(sizeof(string), sizeof(vector<int>))
     
    int main()
    {
        S s = {"Hello, world"};
        std::cout << "s.str = " << s.str << '\n';
        s.str.~basic_string();
    
        new (&s.vec) std::vector<int>;
        s.vec.push_back(10);
        std::cout << s.vec.size() << '\n';
        s.vec.~vector();
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Aug 2002
    Posts
    756

    Re: Memory leaks detected

    2kaud,
    Quote Originally Posted by 2kaud View Post
    Are you sure that ValuueType should be a union and not a struct? A union is a special class type that can hold only one of its non-static data members at a time. but in the constructor for ValuueType you are tying to initialise 3 of it's 4 members together???? You should only initialise the active union member. If a union has one member which is a class, then when referencing another member, the destructor should be called first. eg

    Code:
    #include <iostream>
    #include <string>
    #include <vector>
     
    union S
    {
        std::string str;
        std::vector<int> vec;
        ~S() {} // Will call destructor for the current active member
    };          // the whole union occupies max(sizeof(string), sizeof(vector<int>))
     
    int main()
    {
        S s = {"Hello, world"};
        std::cout << "s.str = " << s.str << '\n';
        s.str.~basic_string();
    
        new (&s.vec) std::vector<int>;
        s.vec.push_back(10);
        std::cout << s.vec.size() << '\n';
        s.vec.~vector();
    }
    So basically what you are saying is that in order to fix it I should initialize only one member in constructor of the
    Code:
    union ValueType
    ? I.e,.:

    Code:
    ValuueType() : intValue( 0 ) {}
    right?

    That class sjould contain the record from the DB and I'm just trying to optimize it with the union as its probably easier to work with.

    BTW, obviously the code in the OP was suppose to read:

    Code:
    std::vector<DataEditFiield> vec;
    vec.push_back( DataEditFiield( 1, 1 ) );
    Thank you.

  4. #4
    Join Date
    Aug 2002
    Posts
    756

    Re: Memory leaks detected

    2kaud,
    I commented ut that code and now I have a crash.

    The code now is:

    Code:
            ValuueType() : intValue( 0 )/*, doubleValue( 0.0 ), stringValue( L"" )*/  {}
    and the crash happens in:

    Code:
                value.stringValue = field.value.stringValue;
    With the following code:

    Code:
    std::vector<DataEditFiield> vec;
    vec.push_back( DataEditFiield( 1 ) );
    vec.push_back( DataEditField( L"mytext" );

    Thank you.

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Memory leaks detected

    There are several issues with the code when using with union. The code below compiles and runs OK with VS2019:

    Code:
    #include <vector>
    #include <string>
    #include <iostream>
    
    enum {INTEGER_TYPE = 1, DOUBLE_TYPE, STRING_TYPE, BLOB_TYPE};
    
    struct DataEditFiield
    {
    	int type, m_size, m_precision;
    
    	union ValuueType
    	{
    		void* blobValue;
    		int intValue;
    		double doubleValue;
    		std::wstring stringValue;
    
    		ValuueType() : stringValue() {}
    		ValuueType(int value) : intValue(value) {}
    		ValuueType(double value) : doubleValue(value) {}
    		ValuueType(const std::wstring& value) : stringValue(value) {}
    		ValuueType(const wchar_t* value) : stringValue(value) {}
    		ValuueType(const void* value) : blobValue(const_cast<void*>(value)) {}
    
    
    		//NO ONLY ONE OF THESE CAN HAVE A VALUE AT ANY TIME!!!!!!!!!!!
    		//************************************************************
    
    		/*
    		ValuueType(const ValuueType& myvalue)
    		{
    			stringValue = myvalue.stringValue;
    			intValue = myvalue.intValue;
    			doubleValue = myvalue.doubleValue;
    			blobValue = myvalue.blobValue;
    			longvalue = myvalue.longvalue;
    		}
    		*/
    
    		// Provide as needed
    		ValuueType(const ValuueType&) = delete;
    		ValuueType& operator=(const ValuueType&) = delete;
    
    		__int64 longvalue;
    		ValuueType(__int64 value) : longvalue(value) {}
    		~ValuueType() noexcept {}
    	} value;
    
    	DataEditFiield(int myvalue) : type(INTEGER_TYPE), m_size(0), m_precision(0), value(myvalue) { }
    
    	DataEditFiield(double myvalue, int size, int precision) : type(DOUBLE_TYPE), m_size(size), m_precision(precision), value(myvalue) { }
    
    	DataEditFiield(const std::wstring& myvalue) : type(STRING_TYPE), m_size(0), m_precision(0), value(myvalue) {}
    
    	DataEditFiield(const void* myvalue) : type(BLOB_TYPE), m_size(0), m_precision(0), value(myvalue) {}
    
    	DataEditFiield(const wchar_t* myvalue) : type(STRING_TYPE), m_size(0), m_precision(0), value(myvalue) {}
    
    	DataEditFiield(__int64 myvalue) : type(INTEGER_TYPE), m_size(0), m_precision(0), value(myvalue) {}
    
    	DataEditFiield(const DataEditFiield& field)
    	{
    		// Default ValuueType is string so that assignment works
    		switch (field.type)
    		{
    			case INTEGER_TYPE:
    				value.intValue = field.value.intValue;
    				break;
    
    			case DOUBLE_TYPE:
    				value.doubleValue = field.value.doubleValue;
    				break;
    
    			case STRING_TYPE:
    				value.stringValue = field.value.stringValue;
    				break;
    
    			case BLOB_TYPE:
    				value.blobValue = field.value.blobValue;
    				break;
    		}
    
    		type = field.type;
    		m_size = field.m_size;
    		m_precision = field.m_precision;
    	}
    
    	//NEEDS TO BE PROVIDED
    	DataEditFiield& operator=(const DataEditFiield&) = delete;
    
    	~DataEditFiield()
    	{
    		using std::wstring;
    
    		if (type == STRING_TYPE)
    			value.stringValue.~wstring();
    	}
    };
    
    std::wostream& operator<<(std::wostream& os, const DataEditFiield& field)
    {
    	// Default ValuueType is string so that assignment works
    	switch (field.type)
    	{
    		case INTEGER_TYPE:
    			os << field.value.intValue;
    			break;
    
    		case DOUBLE_TYPE:
    			os << field.value.doubleValue;
    			break;
    
    		case STRING_TYPE:
    			os << field.value.stringValue;
    			break;
    
    		case BLOB_TYPE:
    			os << field.value.blobValue;
    			break;
    	}
    
    	return os;
    }
    
    
    int main()
    {
    	std::vector<DataEditFiield> vec;
    
    	vec.push_back(DataEditFiield(1));
    	vec.push_back(DataEditFiield(L"mytext"));
    
    	std::cout << vec.size() << " items\n\n";
    
    	for (size_t i = 0; i < vec.size(); ++i)
    		std::wcout << vec[i] << '\n';
    }
    which displays:

    Code:
    2 items
    
    1
    mytext
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Join Date
    Aug 2002
    Posts
    756

    Re: Memory leaks detected

    2kaud,
    Thank you for the code.
    Works like a charm.

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