[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference pamsrc::objectbroker_development

Title:ObjectBroker Development - BEA Systems' CORBA
Notice:See note 2 for kit locations; note 4 for training
Moderator:RECV::GUMBELd
Created:Thu Dec 27 1990
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2482
Total number of notes:13057

2455.0. "Memory leak OBB 2.7-11!!!" by UTROP1::OLERUD_G () Tue Mar 18 1997 10:25

    Memory leak!!!
    
    We have noticed a memory leak in OBB 2.7-11 for NT 4.0.
    If a client invokes a method which returnes an object reference you
    leak about 2Kbyte each call at the client side!!!!! The server side
    seems not to leak.
    
    This is even true when using Quickstart clients.
    I'm using the NT Taskmanager to monitor the memory usage.
    
    We (John Donaldson) tried this on VMS OBB 2.7-10 which seems not to
    leak in this situation.
    
    
    Gunnar
    
T.RTitleUserPersonal
Name
DateLines
2455.1Need more info to reproduce thisRECV::VLATASWARNING: Do not swallow the battery doorWed Mar 19 1997 10:2013
    
    I tried to reproduce this (using quickstart), but wasn't able to.
    I watched the client process with the Performance monitor and the task
    manager and the memory usage stayed flat as it looped through a few
    thousand invokes (Purify also verified that no memory was leaked
    after rundown).
    
    Some questions:
    	1) What service pack level is installed on the NT 4.0 machine?
        2) Which language bindings are you using?
        3) Was the object an out argument, or was it the return value?
    
    Tony
2455.2Some anwswersUTROP1::OLERUD_GWed Mar 19 1997 10:4816
    Tony,
    
 >>           1) What service pack level is installed on the NT 4.0 machine?
 	
    We are using service pack 1.
    
 >>           2) Which language bindings are you using?
    
 	We are using C++ bindings
    			
 >>           3) Was the object an out argument, or was it the return value?
    
    The object reference was returned as a return value.
    
    Cheers
    Gunnar
2455.3No luck yet, can you post the IDLSEND::VLATASWARNING: Do not swallow the battery doorWed Mar 19 1997 12:146
    
    I still haven't been able to reproduce this. Could you post the IDL
    that you used for the Quickstart reproducer.
    
    thanks
    Tony
2455.4here it is - nothing specialLEMAN::DONALDSONFroggisattva! Froggisattva!Fri Mar 21 1997 11:1353
Tony,

thanks for the attention and sorry for the slow turnaround.
Gunnar and I are working on site with the customer and it's
pretty difficult to keep in touch. Today I'm back at my
Digital desk (821-5032) and so of course it's difficult to
try things in the customer environment!

The IDL below shows the problem. However, I have to say that 
there is nothing special about it. It's just what we've
reduced things to. At first we suspected something in the
way we were doing things (we have a large implementation by
now and lots of things are happening). We also have servers
with no memory leaks.

However, we then generated a quickstart client and server,
modified them to loop lots of times (loop in the client
and comment out exit_mainloop in the server). Then we
monitor with the task monitor that comes with NT4.

We reliably leak about 2k. That's if I Exchange->startSession
and then Session->close (see idl). If all I do is 
Exchange->startSession then I leak a little bit less.
(Of course I had to modify the quickstart code a little to
get the Session->close on the Session returned by 
Exchange->startSession).

As Gunnar said earlier we *dont* see this on VMS. And if
I could figure a simple way to monitor memory on W95 then
I'd check things there.

We can arrange to send you some code if you want but I 
assure you its nothing special.

John D.

IDL: ------------------------------------------------------

module TSA
{

    interface Session
    {
        void close();
    };

    interface Exchange
    {
        Session startSession( in string name);
    };

};

2455.5Found 2 client leaks, 1 server leakSEND::VLATASWARNING: Do not swallow the battery doorTue Mar 25 1997 12:2067
Hi John,

   Sorry for the delay, I just got back around to trying your IDL.

>> The IDL below shows the problem. However, I have to say that
>> there is nothing special about it. 

   Your IDL did show the leaks (My IDL used "Object" yours used
   "Session", this was an important difference. I'm suprised that
   the leaks only showed up in V2.7-11 and only on NT for you.
   The leaks are pretty generic and I would expect would happen
   everywhere. I also found a leak in the server.

   I will be entering PTRs on these separately and will post the
   PTR numbers when I enter them.

   Two of the leaks were the result of generated code creating a
   CORBA::Object_ptr, then narrowing it to the result Session, and
   never releasing the original CORBA::Object_ptr.

   Looks like there are a few leaks in the client:

	1) The overloaded routine for extracting the object from the
	   marshalbuffer isn't releasing the tmp_obj_ptr.

	      Workaround A:

		Change your IDL to return an Object, and have your client
		narrow the Object to Session.

	      Workaround B: (Requires editing generated code)

		Leave "Session" as the return type and edit the generated
		routine in the typecode module:

		 OBB::MarshalBuf &operator>>(OBB::MarshalBuf &mb,
					     TSA::Session_ptr &_obj)

		Add in the following after the _narrow call:

		{
		CORBA::Environment tmp_ev;
		CORBA::release(tmp_obj_ptr, tmp_ev);
		}

	2) The Quickstart code for TSAExchangeStartSession allocates a
	   string that it never frees.

	   Workaround:
		Edit generated client call routime TSAExchangestartsession
		Add in the following after the call to
		ExchangeObj->startsession():

			CORBA::string_free(name);

    For the leak in the Server:

	1) The Quickstart code for ExchaneImpl::ExchangeImpl_startsession wasn't
	   releasing the temp_object after it narrowed it.

	   Workaround:
		Add in the following after the _narrow call:

		CORBA::release(temp_object, ev);

thanks
Tony
2455.6Forgot to mention another server side workaround..SEND::VLATASWARNING: Do not swallow the battery doorTue Mar 25 1997 12:235
    
    Also note that if you change your IDL to use "Object" the server
    side leak will go away as well...
    
Tony
2455.7PTR numbersSEND::VLATASWARNING: Do not swallow the battery doorWed Mar 26 1997 12:447
    The PTR numbers for tracking those leaks are:
    
    	16-3-252
    	16-3-253
    	16-3-254
    
    Tony
2455.8TypeCode fix programUTROP1::OLERUD_GThu Mar 27 1997 08:05166
    This is now the fourth fix program I've written to fix OBB generated
    code. I'm becoming a real expert in doing this. 
    Well, I've written a type code fix program that can be used to remove
    the memory leak problem described in this note.
    
    Gunnar
    ---------------------------------------------------------------------
    /*
     *
     * TypeCodeFix - a program to fixup the generated TypeCode file from
    ObjectBroker
     *
     * This program uses STL and has been written in Visual C++ 4.2.
     *
     *	Description:
     *		This program reads in a generated type code file and adds a
    release
     *		statement of a temporary object in all routines of type:
     *
     *			OBB::MarshalBuf &operator>>(OBB::MarshalBuf &mb,
    <module>::<interface>_ptr &obj)
     *
     *		The search criteria used is: "::_narrow(tmp_obj_ptr);"
     *		which seems appropriate in this case.
     *
     *	Authors: Olerud,	27 March 1997
     *
     *	History:
     *		27 March	1997	Gunnar Olerud, First version
     *
     */
    
    #ifdef WIN32
    #pragma warning (disable: 4786)	// identifier was truncated to
    '255' characters
    #endif
    #include <string>
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <iterator>
    
    #define MAX_LINE_SIZE	1024
    
    typedef vector <string, allocator<string> > LineVector;
    
    // Forward declarations
    bool ReadFile (string filename, LineVector& inLines);
    bool creOutputFile(string fileName, LineVector& outLines);
    bool fixupRelease(LineVector& inLines, LineVector& outLines);
    
    // Here it comes! The main program.
    int
    main(int argc, char *argv[])
    {
    	LineVector inLines;
    	LineVector outLines;
    
    	if (argc < 2)
    	{
    		cout << "TypeCodeFix: Not enough parameters, syntax:" <<
    endl;
    		cout << "TypeCodeFix <TypeCode file>" << endl;
    		return 1;
    	}
    
    	// read the type code file into a vector
    	if (!ReadFile (argv[1], inLines))
    	{
    		return 1;
    	}
    
    	if (!fixupRelease(inLines, outLines))
    	{
    		cout << "TypeCodeFix: No changes made" << endl;
    		return 0;
    	}
    	// output the default vector to the new IML file
    	creOutputFile(argv[1], outLines);
    	return 0;
    }
    
    bool 
    ReadFile (string fileName, LineVector& lines)
    {
    	char single_line[MAX_LINE_SIZE];
    
    	ios_base::openmode mode = ios_base::in;
    	ifstream infile (fileName.c_str(), mode);
    	if (!infile.is_open())
    	{
    		cout << "TypeCodeFix: Can't open file '" << fileName << "'"
    << endl;
    		return false;
    	}
    
    	cout << "Reading from file " << fileName << endl;
    
    	while (infile.getline (single_line, sizeof(single_line)))
    	{
    		lines.push_back(single_line);
    	}
    	infile.close ();
    
    	return true;
    }
    
    
    bool
    creOutputFile(string fileName, LineVector& lines)
    {
    	ofstream fileout (fileName.c_str());
    	if (!fileout.is_open())
    	{
    		cout << "TypeCodeFix: Can't create file '" << fileName <<
    "'" << endl;
    		return false;
    	}
    
    	cout << "Writing to file " << fileName << endl;
    
    	ostream_iterator<string, char, struct char_traits<char> >
    out(fileout, "\n");
    	copy(lines.begin(), lines.end(), out);
    
    	fileout.close();
    	return true;
    } // End of creOutputFile(string fileName, LineVector& lines)
    
    
    bool
    fixupRelease(LineVector& inLines, LineVector& outLines)
    {
    	int position;
    	bool isChanged = false;
    	string searchKey = "::_narrow(tmp_obj_ptr);";
    	LineVector addLines;
    
    	addLines.push_back ("\t{");
    	addLines.push_back ("\t\tCORBA::Environment tmp_ev;");
    	addLines.push_back ("\t\tCORBA::release(tmp_obj_ptr, tmp_ev);");
    	addLines.push_back ("\t}");
    
    	LineVector::iterator lineIT;
    	for (lineIT = inLines.begin(); lineIT != inLines.end(); lineIT++)
    	{
    		outLines.push_back(*lineIT);
    		if ((position = (*lineIT).find(searchKey)) > 0)
    		{
    			//the narrow found. Add the release statement if
    not already there
    			lineIT++;
    			if (!equal (addLines.begin(), addLines.end(),
    lineIT))
    			{
    				copy (addLines.begin(), addLines.end(),
    back_inserter(outLines));
    				isChanged = true;
    			}
    		}
    	}
    	return isChanged;
    
    } // end of fixupRelease(LineVector& lines)
    
    
2455.9Correct version of TypeCodeFix programUTROP1::OLERUD_GThu Mar 27 1997 09:49163
    Woops!!! I was too quick to enter the code in .7. Hopefully this
    version works better.
    
    Gunnar
    ----------------------------------------------------------------
    /*
     *
     * TypeCodeFix - a program to fixup the generated TypeCode file from
    ObjectBroker
     *
     * This program uses STL and has been written in Visual C++ 4.2.
     *
     *	Description:
     *		This program reads in a generated type code file and adds a
    release
     *		statement of a temporary object in all routines of type:
     *
     *			OBB::MarshalBuf &operator>>(OBB::MarshalBuf &mb,
    <module>::<interface>_ptr &obj)
     *
     *		The search criteria used is: "::_narrow(tmp_obj_ptr);"
     *		which seems appropriate in this case.
     *
     *	Authors: Olerud,	27 March 1997
     *
     *	History:
     *		27 March	1997	Gunnar Olerud, First version
     *
     */
    
    #ifdef WIN32
    #pragma warning (disable: 4786)	// identifier was truncated to
    '255' characters
    #endif
    #include <string>
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <iterator>
    
    #define MAX_LINE_SIZE	1024
    
    typedef vector <string, allocator<string> > LineVector;
    
    // Forward declarations
    bool ReadFile (string filename, LineVector& inLines);
    bool creOutputFile(string fileName, LineVector& outLines);
    bool fixupRelease(LineVector& inLines, LineVector& outLines);
    
    // Here it comes! The main program.
    int
    main(int argc, char *argv[])
    {
    	LineVector inLines;
    	LineVector outLines;
    
    	if (argc < 2)
    	{
    		cout << "TypeCodeFix: Not enough parameters, syntax:" <<
    endl;
    		cout << "TypeCodeFix <TypeCode file>" << endl;
    		return 1;
    	}
    
    	// read the type code file into a vector
    	if (!ReadFile (argv[1], inLines))
    	{
    		return 1;
    	}
    
    	if (!fixupRelease(inLines, outLines))
    	{
    		cout << "TypeCodeFix: No changes made" << endl;
    		return 0;
    	}
    	// output the default vector to the new IML file
    	creOutputFile(argv[1], outLines);
    	return 0;
    }
    
    bool 
    ReadFile (string fileName, LineVector& lines)
    {
    	char single_line[MAX_LINE_SIZE];
    
    	ios_base::openmode mode = ios_base::in;
    	ifstream infile (fileName.c_str(), mode);
    	if (!infile.is_open())
    	{
    		cout << "TypeCodeFix: Can't open file '" << fileName << "'"
    << endl;
    		return false;
    	}
    
    	cout << "Reading from file " << fileName << endl;
    
    	while (infile.getline (single_line, sizeof(single_line)))
    	{
    		lines.push_back(single_line);
    	}
    	infile.close ();
    
    	return true;
    }
    
    
    bool
    creOutputFile(string fileName, LineVector& lines)
    {
    	ofstream fileout (fileName.c_str());
    	if (!fileout.is_open())
    	{
    		cout << "TypeCodeFix: Can't create file '" << fileName <<
    "'" << endl;
    		return false;
    	}
    
    	cout << "Writing to file " << fileName << endl;
    
    	ostream_iterator<string, char, struct char_traits<char> >
    out(fileout, "\n");
    	copy(lines.begin(), lines.end(), out);
    
    	fileout.close();
    	return true;
    } // End of creOutputFile(string fileName, LineVector& lines)
    
    
    bool
    fixupRelease(LineVector& inLines, LineVector& outLines)
    {
    	int position;
    	bool isChanged = false;
    	string searchKey = "::_narrow(tmp_obj_ptr);";
    	LineVector addLines;
    
    	addLines.push_back ("\t{");
    	addLines.push_back ("\t\tCORBA::Environment tmp_ev;");
    	addLines.push_back ("\t\tCORBA::release(tmp_obj_ptr, tmp_ev);");
    	addLines.push_back ("\t}");
    
    	LineVector::iterator lineIT;
    	for (lineIT = inLines.begin(); lineIT != inLines.end(); lineIT++)
    	{
    		outLines.push_back(*lineIT);
    		if ((position = (*lineIT).find(searchKey)) > 0)
    		{
    			//the narrow found. Add the release statement if
    not already there
    			if (!equal (addLines.begin(), addLines.end(),
    lineIT+1))
    			{
    				copy (addLines.begin(), addLines.end(),
    back_inserter(outLines));
    				isChanged = true;
    			}
    		}
    	}
    	return isChanged;
    
    } // end of fixupRelease(LineVector& lines)