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