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