Thread: Why this kind of error after normal execution?

  1. #1
    "Why use dynamic memory?"
    Join Date
    Aug 2006
    Posts
    186

    Why this kind of error after normal execution?

    I tried to program a simple data base for employees. Everytime u wanna add a new employee, the dynamic array goes up in size and add one more empty slot for future addition.
    I compiled the code and ran it, after adding 17 employees in the array and showing em on the screen, the next allocation screws up the program!!

    this is the code :

    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    #include <string>
    
    
    using namespace std;
    
    class Employee
    {
    public:
    	//Default Constructor 
    	Employee();
    	//Constructor
    	Employee(string name, int age, int salary);
    	//Destructor
    	~Employee();
    
    	//Methods
    	void EditInfo();
    	void EditName();
    	void EditAge();
    	void EditSalary();
    
    	//Accessors
    	string GetName();
    	int	   GetAge();
    	int    GetSalary();
    
    	//Data Members
    private:
    	string m_Name;
    	int	   m_Age;
    	int	   m_Salary;
    };
    
    //Default Constructor
    Employee::Employee()
    {
    }
    
    //Constructor
    Employee::Employee(string name, int age, int salary): m_Name(name), m_Age(age), m_Salary(salary)
    {
    }
    
    //Destructor
    Employee::~Employee()
    {
    }
    
    //Edititing information function 
    void Employee::EditInfo()
    {
    	string sTemp;
    	int    iTemp;
    
    	cout << "Enter the name: "; cin >> sTemp;
    	cout << endl;
    	m_Name = sTemp;
    
    	cout << "Enter the age: "; cin >> iTemp;
    	cout << endl;
    	m_Age = iTemp;
    
    	cout << "Enter the salary: "; cin >> iTemp;
    	m_Salary = iTemp;
    }
    
    //Accessor to m_Salary
    int Employee::GetSalary()
    {
    	return m_Salary;
    }
    
    //Accessor to m_Age 
    int Employee::GetAge()
    {
    	return m_Age;
    }
    
    //Accessor to m_Name
    string Employee::GetName()
    {
    	return m_Name;
    }
    
    //Edit m_Salary
    void Employee::EditSalary()
    {
    	int temp;
    	cout << "Enter the new salary: "; cin >> temp;
    	m_Salary = temp;
    }
    
    //Edit m_Age
    void Employee::EditAge()
    {
    	int temp;
    	cout << "Enter the new age: "; cin >> temp;
    	m_Age = temp;
    }
    
    //Edit m_Name
    void Employee::EditName()
    {
    	string temp;
    	cout << "Enter the new name: "; cin >> temp;
    	m_Name = temp;
    }
    
    
    void IncreaseSlots(int* NumOfEmps);
    void CleanDataBase(Employee** DB, int* NumOfEmps);
    
    
    int main()
    {
    	int NOE = 1;
    	Employee** p_DB = new Employee*[NOE];
    	if(!p_DB[NOE])
    	{
    		cout << "Error: Data Base could not be created!" << endl;
    		cout << "No enough memory for allocation!" << endl;
    		return 0;
    	}
    
    	bool quit = false;
    	while(!quit)
    	{
    		cout << "What do you want to do: " << endl;
    		cout << "1)Add Employee" << endl;
    		cout << "2)Show Data Base" << endl;
    		cout << "3)Clear Data Base" << endl;
    		cout << "4)Quit the program" << endl;
    		int choice;
    		cin >> choice;
    		cout << endl;
    		switch(choice)
    		{
    		case 1:
    			if(NOE == 1)
    			{
    				p_DB[NOE-1] = new Employee();
    				if(!p_DB[NOE-1])
    				{
    					cout << "Error: no enough memory for allocation!";
    					return 0;
    				}
    				p_DB[NOE-1]->EditName();
    				cout << endl;
    				IncreaseSlots(&NOE);
    			}
    			else
    			{
    				p_DB[NOE-1] = new Employee();
    				if(!p_DB[NOE-1])
    				{
    					cout << "Error: no enough memory for allocation!";
    					return 0;
    				}
    				p_DB[NOE-1]->EditName();
    				cout << endl;
    				IncreaseSlots(&NOE);	
    			}
    			break;
    
    		case 2:
    			for(int i = 0; i < (NOE-1); ++i)
    			{
    				string name = p_DB[i]->GetName();
    				cout << name;
    				cout << endl;
    			}
    			cout << NOE;
    			cout << endl;
    			break;
    
    		case 3:
    			
    			cout << "Data Base cleared!" << endl;
    			CleanDataBase(p_DB, &NOE);
    
    		case 4:
    			quit = true;
    		}
    	}
    
    	CleanDataBase(p_DB, &NOE);
    	
    	char q;
    	cin >> q;
    	return 0;
    }
    
    void IncreaseSlots(int* NumOfEmps)
    {
    	*NumOfEmps += 1;
    }
    
    void CleanDataBase(Employee** p_DB, int *NumOfEmps)
    {
    	if(p_DB)
    	{
    		for(int i = 0; i < *(NumOfEmps); ++i)
    			if(p_DB[i])
    			{
    				delete [] p_DB[i];
    				p_DB[i] = 0;
    			}
    			delete p_DB;
    			p_DB = 0;
    	}
    }
    PS: What is wrong with "ClearDataBase" function??
    Last edited by Hussain Hani; 06-30-2007 at 05:22 PM.
    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg."-Bjarne Stroustrup
    Nearing the end of finishing my 2D card game! I have to work on its 'manifesto' though <_<

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I'm not sure why you are trying to create your own resizable dynamic array when standard C++ comes with one already.

    You say that the array goes up in size, but there is no code to create a larger array. All you do is increment your count and add to the array that has room for only a single Employee*. You just got unlucky that it worked 17 times before it crashed. If you wanted to learn how a resiable dynamic array works and do it yourself, you would have to create a new array with a larger size and copy over each pointer from the old array.

    >> PS: What is wrong with "ClearDataBase" function??
    You use delete [] on a regular pointer and delete on an array. That's backwards.

    So, why aren't you using vector?

  3. #3
    "Why use dynamic memory?"
    Join Date
    Aug 2006
    Posts
    186
    I tried to modify the code. But making NOE initially equals zero, so the data base is empty. And when you wanna add employee it adds just one room for it. So this hopefully will deal with the previous problem that the array resize and add empty slot.
    But the problem is the same, it crashes.
    I use arrays cuz they are low-level and pushe me to my limit . I could use some vector but I dont wanna to, to be honest.
    Last edited by Hussain Hani; 06-30-2007 at 05:35 PM.
    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg."-Bjarne Stroustrup
    Nearing the end of finishing my 2D card game! I have to work on its 'manifesto' though <_<

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> And when you wanna add employee it adds just one room for it.
    How are you adding room for it? That takes a lot of code, none of which is in the code you posted.

    You have to create a new temporary array with the new size, then copy over the contents of the old array, then delete the old array, then assign the pointer to the temporary array to the original pointer.

  5. #5
    "Why use dynamic memory?"
    Join Date
    Aug 2006
    Posts
    186
    . I increase the array size by making the size a variable. This is an example
    Code:
    //Making a dynamic array based on a variable
    int size = 0;
    int* iArray = new int[size]
    
    //Since the array size is based on the variable, we can change variable to resize the array
    //can we not?
    if(//the user wanna add new employee)
    size += 1;
    this is the new code i forgot to post
    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    #include <string>
    
    
    using namespace std;
    
    class Employee
    {
    public:
    	//Default Constructor 
    	Employee();
    	//Constructor
    	Employee(string name, int age, int salary);
    	//Destructor
    	~Employee();
    
    	//Methods
    	void EditInfo();
    	void EditName();
    	void EditAge();
    	void EditSalary();
    
    	//Accessors
    	string GetName();
    	int	   GetAge();
    	int    GetSalary();
    
    	//Data Members
    private:
    	string m_Name;
    	int	   m_Age;
    	int	   m_Salary;
    };
    
    //Default Constructor
    Employee::Employee()
    {
    }
    
    //Constructor
    Employee::Employee(string name, int age, int salary): m_Name(name), m_Age(age), m_Salary(salary)
    {
    }
    
    //Destructor
    Employee::~Employee()
    {
    }
    
    //Edititing information function 
    void Employee::EditInfo()
    {
    	string sTemp;
    	int    iTemp;
    
    	cout << "Enter the name: "; cin >> sTemp;
    	cout << endl;
    	m_Name = sTemp;
    
    	cout << "Enter the age: "; cin >> iTemp;
    	cout << endl;
    	m_Age = iTemp;
    
    	cout << "Enter the salary: "; cin >> iTemp;
    	m_Salary = iTemp;
    }
    
    //Accessor to m_Salary
    int Employee::GetSalary()
    {
    	return m_Salary;
    }
    
    //Accessor to m_Age 
    int Employee::GetAge()
    {
    	return m_Age;
    }
    
    //Accessor to m_Name
    string Employee::GetName()
    {
    	return m_Name;
    }
    
    //Edit m_Salary
    void Employee::EditSalary()
    {
    	int temp;
    	cout << "Enter the new salary: "; cin >> temp;
    	m_Salary = temp;
    }
    
    //Edit m_Age
    void Employee::EditAge()
    {
    	int temp;
    	cout << "Enter the new age: "; cin >> temp;
    	m_Age = temp;
    }
    
    //Edit m_Name
    void Employee::EditName()
    {
    	string temp;
    	cout << "Enter the new name: "; cin >> temp;
    	m_Name = temp;
    }
    
    
    void IncreaseSlots(int* NumOfEmps);
    void CleanDataBase(Employee** DB, int* NumOfEmps);
    
    
    int main()
    {
    	int NOE = 0;
    	Employee** p_DB = new Employee*[NOE];
    	if(!p_DB[NOE])
    	{
    		cout << "Error: Data Base could not be created!" << endl;
    		cout << "No enough memory for allocation!" << endl;
    		return 0;
    	}
    
    	bool quit = false;
    	while(!quit)
    	{
    		cout << "What do you want to do: " << endl;
    		cout << "1)Add Employee" << endl;
    		cout << "2)Show Data Base" << endl;
    		cout << "3)Clear Data Base" << endl;
    		cout << "4)Quit the program" << endl;
    		int choice;
    		cin >> choice;
    		cout << endl;
    		switch(choice)
    		{
    		case 1:
    			IncreaseSlots(&NOE);
    			p_DB[NOE-1] = new Employee();
    			if(!p_DB[NOE-1])
    			{
    				cout << "Error: no enough memory for allocation!";
    				return 0;
    			}
    			p_DB[NOE-1]->EditName();
    			cout << endl;
    			break;
    
    		case 2:
    			for(int i = 0; i < NOE; ++i)
    			{
    				string name = p_DB[i]->GetName();
    				cout << name;
    				cout << endl;
    			}
    			cout << NOE;
    			cout << endl;
    			break;
    
    		case 3:
    			cout << "Data Base cleared!" << endl;
    			CleanDataBase(p_DB, &NOE);
    
    		case 4:
    			quit = true;
    		}
    	}
    
    	CleanDataBase(p_DB, &NOE);
    	
    	char q;
    	cin >> q;
    	return 0;
    }
    
    void IncreaseSlots(int* NumOfEmps)
    {
    	*NumOfEmps += 1;
    }
    
    void CleanDataBase(Employee** p_DB, int *NumOfEmps)
    {
    	if(p_DB)
    	{
    		for(int i = 0; i < *(NumOfEmps); ++i)
    			if(p_DB[i])
    			{
    				delete  p_DB[i];
    				p_DB[i] = 0;
    			}
    			delete [] p_DB;
    			p_DB = 0;
    	}
    }
    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg."-Bjarne Stroustrup
    Nearing the end of finishing my 2D card game! I have to work on its 'manifesto' though <_<

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> I increase the array size by making the size a variable.
    That size variable is only used by the array once. When the array is first created, it gets the value of size (in this case that's zero) and makes enough room for that many values. Later, when you increase the size variable, it has no effect on the array. The two are not tied to each other in any way. It's the same as if you did this:
    Code:
    int* iArray = new int[0];
    
    int size = 0;
    
    //Since the array size is based on the variable, we can change variable to resize the array
    //can we not?
    if(//the user wanna add new employee)
    size += 1;

  7. #7
    "Why use dynamic memory?"
    Join Date
    Aug 2006
    Posts
    186
    then how come when I increase the variable, the array's size gets larger and can have more objects?? !!
    "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg."-Bjarne Stroustrup
    Nearing the end of finishing my 2D card game! I have to work on its 'manifesto' though <_<

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The array size does not get larger. You just start using memory that doesn't belong to your program. Since the compiler doesn't stop you from doing that with built-in arrays, you just get undefined behavior. Eventually you attempt to modify memory that can't be modified, or you change data that is being used by another part of your code, or you do other bad things to your memory and the program crashes.

    That's why these things are so "dangerous" and why C++ library classes are preferred. They do a better job of helping you avoid these situations, so there is less likelihood of crashing or worse, getting slightly incorrect results.

  9. #9
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    C++ has something to say teh Failure of memory allocation set_new_handler() on new.h
    You should Use that instead of
    Code:
    if(!p_DB[NOE])
    Its like
    Code:
    #include <iostream>
    #include <new>
    using namespace std;
    const char* bp = "\a\n\a\n";
    const int gap = 32000;
    static void trg_error(){
    	cout<<bp<<"cant Allocate Memmory"<<bp<<endl;
    	exit(1);
    }
    int main(){
    	set_new_handler(trg_error);//Here I am using it
    	for(unsigned int i = gap;;i += gap){
    		int *pInt = new int[gap];
    		cout<<"Grabbing Memmory\t"<<i<<" Bytes"<<endl;
    	}
      return 0;
    }
    And why its
    Code:
    Employee** p_DB = new Employee*[NOE];
    Instead of
    Code:
    Employee* p_DB = new Employee[NOE];
    Isnt this Enough
    I think temp is not needed here its a memory wastage
    Code:
    void Employee::EditName()
    {
      cout << "Enter the new name: "; 
      cin >> m_Name;
    }
    Last edited by noobcpp; 06-30-2007 at 11:04 PM.

  10. #10
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    why to use arrays if there is a vector included?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    See post #3, "I use arrays cuz they are low-level and pushe me to my limit . I could use some vector but I dont wanna to, to be honest."

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I use arrays cuz they are low-level and pushe me to my limit . I could use some vector but I dont wanna to, to be honest.
    Write your own vector (and list, set, map, etc) class template to push yourself to your limit, thereafter use standard library containers (and those of Boost) unless that option is somehow not available to you.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    The larch
    Join Date
    May 2006
    Posts
    3,573
    . I increase the array size by making the size a variable. This is an example
    Code:
    //Making a dynamic array based on a variable
    int size = 0;
    int* iArray = new int[size]
    
    //Since the array size is based on the variable, we can change variable to resize the array
    //can we not?
    if(//the user wanna add new employee)
    size += 1;
    This is really analogous to hoping that after
    Code:
    string s("Hello "), t("world");
    s += t;
    t = "moon";
    string s would contain the phrase "Hello moon".

    You would have been better off, if the undefined behaviour hadn't allowed you to "add" 17 Employees before crashing, but crashed immediately.

    I use arrays cuz they are low-level and pushe me to my limit . I could use some vector but I dont wanna to, to be honest.
    Usually a programmer just wants a reliable program with a minimum effort

    For learning purposes there's nothing wrong in pushing yourself to the limits with reinventing the wheel. But since memory management is especially tricky, at least let a class - say EmployeeDatabase - handle it. Otherwise you'll run the constant risk of losing some pointer, corrupting some value, leaking memory etc.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Run-time execution for recursive functions.
    By Kempelen in forum C Programming
    Replies: 8
    Last Post: 03-26-2009, 04:00 AM
  2. inet_aton()... Noob needs help with sockets :|
    By Maz in forum C++ Programming
    Replies: 3
    Last Post: 11-22-2005, 04:33 PM
  3. Replies: 12
    Last Post: 06-24-2005, 04:27 PM
  4. HUGE fps jump
    By DavidP in forum Game Programming
    Replies: 23
    Last Post: 07-01-2004, 10:36 AM
  5. difference between register int and normal int
    By GanglyLamb in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 02-25-2003, 04:01 PM