Click here to Skip to main content
15,914,221 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Here i am attaching the piece of code which is giving exception while deleting the memory allocated in heap in destructor.

#include "stdafx.h"
#include <iostream>
using namespace std;
#include <string>
class Employee
{
public:
	char *empName;
	int empRolNo;
public:
	Employee()
	{
		
		cout<<"Default Constructor"<<endl;
		empName = new char[3];
		strcpy_s(empName,strlen(empName),"Chamakuri");
		empRolNo = 111;
	}
	Employee(char *name,int r)
	{
		cout<<"Param Constructor\t"<<this<<endl;
		this->~Employee();
		empName = new char[strlen(name)+1];
		strcpy_s(empName,strlen(empName),name);
		empRolNo=r;
		Employee e3; // Here exception is coming.
	}
	~Employee()
	{
		cout<<"Desstructor\t"<<this<<endl;
		delete []empName;
		empName=NULL;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	Employee e1,e2("Satya",123);
	getchar();
	return 0;
}


This is the exception Code where control is going during exception.

VB
/***
*int _CrtIsValidHeapPointer() - verify pointer is from 'local' heap
*
*Purpose:
*       Verify pointer is not only a valid pointer but also that it is from
*       the 'local' heap. Pointers from another copy of the C runtime (even in the
*       same process) will be caught.
*
*Entry:
*       const void * pUserData     - pointer of interest
*
*Return:
*       TRUE - if valid and from local heap
*       FALSE otherwise
*
*******************************************************************************/
extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
        const void * pUserData
        )
{
        if (!pUserData)
            return FALSE;

        if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
            return FALSE;

        return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}




Can anyone suggest me why its showing exception?
Thanks in advance.
Posted
Comments
Sergey Alexandrovich Kryukov 10-Apr-15 2:00am    
What line?
—SA

your default ctor is allocating a char of size 3 (which isn't big enough), then you're doing a strlen on that - strlen works by walking the pointer until it finds a null, so it could be coming back with ANY number

Then you copy a string that's FAR bigger than 3 chars into it - you've totally biffed your heap at that point

you're doing the same copy in the other ctor - you need the size of the destination (for that safe copy), it doesn't have a strlen because there's nothing in it yet
 
Share this answer
 
v2
Comments
Satya Chamakuri 10-Apr-15 1:43am    
Thank you barneyman.. I changed strcpy_s(empName,strlen(empName),"Chamakuri") to strcpy_s(empName,strlen("Chamakuri"),"Chamakuri") and strcpy_s(empName,strlen(empName),name) to strcpy_s(empName,strlen(name),name) in the above snippet. Its Working fine.
Thank you........
Stefan_Lang 10-Apr-15 5:24am    
That's not correct! The length parameter expected in strcpy_s should denote the size of the buffer that you're copying to. Since you only allocated 3 bytes, the size of this buffer is 3, not strlen(anything)!
C++
this->~Employee();

What is that line? You should never call a destructor directly. This is very advanced stuff for expert only.

C++
strlen(empName)

The above lione is incorrect. You are trying to get the length of an uninitialized string (see Solution 1).

C++
Employee e3; // Here exception is coming.

What is the purpose of creating another employee that is unused at the end of one of the constructor?

C++
public:
	char *empName;
	int empRolNo;

Why are those members public? They should be private.


By the way, you should use std::string instead of your own string handling. Your class would look similar to this:
C++
class Employee
{
private:
    string empName;
    int empRolNo;

public:
    Employee()
    {
        cout << "Default Constructor" << endl;
        empName = "Chamakuri";
        empRolNo = 111;
    }

    Employee(const char *name,int r)
    {
        cout << "Param Constructor\t" << name << endl;
        empName = name;
        empRolNo=r;
    }

    ~Employee()
    {
        cout << "Destructor\t" << empName << endl;
    }
};
 
Share this answer
 
v3
Comments
Satya Chamakuri 13-Apr-15 0:11am    
I agree with Philippe, But i don't know whether my question is valid or not , But how we can allot memory at run time (Dynamically) if we are using string?

Second, Why i am using strlen means i wanted to make the size of member variable is equivalent to that of the string which i am trying to put.
And finally , why i am declaring Employee e3 is just to confirm whether we can declare object in constructor or not.

If i am foolish sorry... Please suggest me if any wrong.
Philippe Mori 13-Apr-15 8:46am    
With string std::class, you don't need to do explicit allocation. This result in much simpler and less error prone code.

strlen returns the len of a null terminated C-style string. This has nothing to do with the allocated length of a characters' array so the call in first constructor is undefined because string content has not yet been initialized.

You can call any constructor from a constructor provides that there is no infinite recursion but it serve no purpose in finding why the code crash and in fact given that the first constructor code is bad, it can make the second constructor crash.
Satya Chamakuri 14-Apr-15 0:10am    
Thank you Philippe.
Thank you barneyman.. I changed strcpy_s(empName,strlen(empName),"Chamakuri") to strcpy_s(empName,strlen("Chamakuri"),"Chamakuri") and strcpy_s(empName,strlen(empName),name) to strcpy_s(empName,strlen(name),name) in the above snippet. Its Working fine.
Thank you........
 
Share this answer
 
Comments
Stefan_Lang 10-Apr-15 5:41am    
not correct: you're telling the function strcpy_s that your buffer empName has a size of 9 characters, and therefore is big enough to hold this string. As a result, the function will copy the entire string into this location, overwriting memory you have never allocated! This may not immediately crash your program, but it's bound to do so very soon(TM), and in unexpected ways!

Basically what you do is the same as pouring a 5 liter can of milk into a 1 liter can, because you told the milkman your can can hold 5 liters. Your can will be filled all right, but it will only hold 1 liter, and the remainder is spilled.

strcpy_s has three parameters:
- the first denotes the memory location where to store the string
- the second tells it how much memory is available at the destination, i. e. how big of a string it can hold
- the third is the string you wish to copy

What it does, then, is compare the amount of memory required to store a copy of the string (the third parameter) to the size of the memory (the second parameter) at the destination location (the third parameter). If the string is bigger than the destination can hold, strcpy_s will only copy the first part of the string, up to the length that the destination can hold. Otherwise, the entire string is copied.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900