[gnu.g++.bug] Virtual memory exhausted.

patrick@cos.com (Patrick Steranka) (12/03/89)

I think I might have a "good one" for you guys this time.  :^)
The error message is:

	Virtual memory exhausted.

How did I get this you might ask?  Well, I compiled the following
program.  I tried to "reproduce" the error on a smaller version
of this program, but I could not get the error to happen.

The error happens when someone defines the constructor member function:
	T(T);
In addition, to having the constructor member function
	T(T&);

As shipped this example will demonstrate the problem (at least it
happens on my system).  By removing the declaration "T(T)" the
code should compile sucessfully and run.  Note: My system is a
SUN 3/280 running SUN OS 3.5 using G++ (1.36.1)

The program is simply a test program that I have written to learn
about how C++ code works.  Please don't ask me what drugs I've
been taking to come up with this stuff.  :^)

==============================  ex4.cc  ==============================
#include <stream.h>


class T {
 private:
    static unsigned int instance_cnt = 0;
    int instance;
    char name[50];
    int val;
    int ref_cnt;
    char* str;

    void alloc(char*);
    void trace(char* action);
 public:
    T();
    T(T&);
    T(T);	// This line causes the bug (or problem) to appear
		// By commenting out the above line the program should compile
    T(char*);
    ~T();
    void operator=(char*);
    void operator=(int);
    void operator=(T&);

// Conversion Operators
    operator char*();
    operator int();
    
    void print();
    
};

void T::alloc(char* var_name)
{
    instance = ++instance_cnt;
    ref_cnt = 1;
    if (var_name == (char*)0)
	sprintf(name,"*noname*%d", instance);
    else
	strcpy(name, var_name);
}


T::T()
{
    alloc((char*)0);
    trace("T::T()");
    val = 0;
    str = 0;
}

T::T(char* vname)
{
    alloc(vname);
    trace("T::T(char* vname)");
    val = 0;
    str = 0;
}

T::T(T& tref)
{
    char buf[50];
    sprintf(buf,"from %s", tref.name);
    alloc(buf);
    trace("T::T(T& tref)");
    val = tref.val;
    if (tref.str){
	str = new char[strlen(tref.str)+1];
	strcpy(str,tref.str);
    }
    else
	str = 0;
}


T::~T()
{
    trace("T::~T()");
    if (--ref_cnt <= 0){
	cout << form("\t\t\tFreeing Resource from %s:%d(%d)\n",
		     name, instance, ref_cnt);
	if (str)
	    delete str;
    }
}


void T::operator=(char* s)
{
    trace("void T::operator=(char* s)");
    str = new char[strlen(s)+1];
    strcpy(str,s);
}

void T::operator=(int arg1)
{
    trace("void T::operator=(int)");
    val = arg1;
}

void T::operator=(T& tref)
{
    trace("In: void T::operator=(T& tref)");
    val = tref.val;
    if (tref.str){
	str = new char[strlen(tref.str)+1];
	strcpy(str,tref.str);
    }
    else
	str = 0;
}



T::operator char*()
{
    trace("T::operator char*()");
    if (str)
	return str;
    else
	return "* No Value *";
}

T::operator int()
{
    trace("T::operator int()");
    return val;
}


void T::print()
{
    cout << form("Printing: %s:%d(%d) Val = %d Str = %s\n",
		 name, instance, ref_cnt, val, str);
}

void T::trace(char* action)
{
    cout << form("\t\tAction [%s] on %s:%d(%d)\n",
		 action, name, instance, ref_cnt);
}

void func1(T var1, T &var2);
void func2(char* arg1, int arg2);

main(int argc, char* argv[])
{
    cout <<"IN MAIN:\n";
    int i = 1;
    char* s = "Test";
    {
	cout << "    In block depth 1\n";
	cout << "    Declare var1 and var2\n";
	T var1("var1");
	T var2("var2");

	cout << "    Assign var1 and var2 values\n";
	var1 = "This is the value for var1";
	var1 = 99;
	var2 = "var2 has this value";
	var2 = 100;

	var1.print();
	var2.print();

	cout << "    Calling func1 NOW with var1 and var2!\n";
	func1(var1, var2);
	cout << "    Returned from func1 NOW!\n\n";


	cout << "    Declare var1_ref and var2_ref\n";
	T& var1_ref = var1;
	T& var2_ref = var2;

	var1_ref.print();
	var2_ref.print();
	
	cout << "    Calling func1 NOW!\n";
	func1(var1_ref, var2_ref);
	cout << "    Returned from func1 NOW!\n\n";

	cout << "    Calling func2 NOW!\n";
	func2(var1, var2_ref);
	cout << "    Returned from func2 NOW!\n";
	cout << "    Exit block depth 1\n";
    }
}


void func1(T var1, T &var2)
{
    cout << "\tIn func1:\n";
    var1.print();
    var2.print();
    cout << "\tExit func1:\n";
}


void func2(char* arg1, int arg2)
{
    cout << "\tIn func2:\n";
    cout << form("arg1 = %s arg2 = %d\n", arg1, arg2);
    cout << "\tExit func1:\n";
}



==============================  ex4.cc  ==============================




====================  Output of compilation  ====================
cd /usr/zulu/patrick/test/c++/ex/
make -k ex4
g++ -o ex4 -g -v ex4.cc
gcc version 1.36.1- (based on GCC 1.36)
 /usr/local/lib/gnu/gcc/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 ex4.cc /usr/tmp/cca22448.cpp
GNU CPP version 1.36
 /usr/local/lib/gnu/gcc/gcc-cc1plus /usr/tmp/cca22448.cpp -quiet -dumpbase ex4.cc -g -version -o /usr/tmp/cca22448.s
GNU C++ version 1.36.1 (based on GCC 1.36) (68k, MIT syntax) compiled by GNU C version 1.36.
default target switches: -m68020 -mc68020 -m68881 -mbitfield
ex4.cc:18: invalid constructor; you probably meant `T (T&)'
ex4.cc: In function int main (int, char **):
ex4.cc:168: Virtual memory exhausted.
make: *** [ex4] Error 1

Compilation exited abnormally with code 1 at Sat Dec  2 21:39:25

====================  Output of compilation  ====================

patrick (Patrick Steranka @ Corporation for Open Systems)
	-- patrick@cos.com
	-- patrick%cos.com@uunet.uu.net
	-- {uunet, sundc, decuac, hqda-ai, hadron}!cos!patrick