So i have the following class
class Community
{
private:
char* Name;
char foundationDate[11];
Person* founder;
int maxMembersCount;
int membersCount;
Person* members;
static int communitiesCount;
.....
and i want to implement a copy constructor :
Community::Community(const Community& other)
{
this->Name = new char[strlen(other.Name)+1];
strcpy(this->Name,other.Name);
strcpy(this->foundationDate,other.foundationDate);
this->founder = other.founder;
this->maxMembersCount = other.maxMembersCount;
this->membersCount = other.membersCount;
this->members = new Person[this->maxMembersCount];
this->members = other.members;
communitiesCount++;
}
but this code crashes whenever i say Community A=B;
so for me this code seems legit, but when i start debugging there is the message: this-> "unable to read memory". Please help me if you need more code example please let me know.
Community::Community(const char* name , char foundDate[],Person* founder,int maxMembers) {
this->Name = new char[strlen(name)+1];
strcpy(this->Name,name);
strcpy(this->foundationDate,foundDate);
this->founder = new Person(founder->getName(),founder->getEGN(),founder->getAddress());
this->maxMembersCount = maxMembers;
this->membersCount = 2;
this->members = new Person[this->maxMembersCount];
communitiesCount++;
}
this is the main constructor of the class which works just fine....
There are multiple problems here, any of whichi could be part or all of the problem.
If Name or foundationDate is not null-terminated on the right-hand side, it will run off and copy bad memory.
If founder or members are owned by the object, you will either leak memory if you don't delete them in the destructor, or cause a whole variety of memory-related problems when you shallow-copy and then delete twice, etc.
To fix this, just make your Name and foundationDate std::string, and then make founder and members be owned by value rather than by pointer. If you absolutely have to allocate them on the heap use a smart pointer such as shared_ptr to hold it instead of a bug-prone raw pointer.
First of all, check that other.Name is filled with a pointer to a null-terminated string, that other.foundationDate contains a null-terminated string. That is, you pass good pointers to strlen and strcpy.
If that's true, check that B in the assignment is accessible altogether.
If that's true too, printf everything. And debug where exactly the exception occurs. Or post whole code that is compilable and which reproduces the error.
Also note that here:
this->members = new Person[this->maxMembersCount];
this->members = other.members;
the first assignment does nothing (leaks memory, in fact) while the second double deletes your memory upon object destruction (if you properly delete[] members).
Related
I have tried to find an answer but couldn't see anything straight forward.
How do I free the allocated memory in the next snippet code:
const char* attStr = strdup(OtherCharStr);
string str(attStr, strlen(attStr));
delete str; //???
C++ uses idiom called RIAA - Resource Acquisition Is Initialization. It means that object lifetime is driven by variable scope.
{
std::string s("foo"); // variable s declaration and string initialization
do_some_stuff(s);
// end of scope of variable s - it is destroyed here
// no need to free(s) or whatever
}
// variable s and the string doesn't exist here, no memory for it is allocated
This applies only for C++ objects that maintain its resources properly (are freeing them in the destructor). Simple pointers doesn't do it - you have to free them yourself:
const char *attStr = strdup(...);
// do something with attStr
free(attStr); // because strdup() documentation says you should free it with free()
Also notice that C++ uses new and delete rather than malloc() and free():
std::string *strPointer = new std::string(...);
// RIAA doesn't work here, because strPointer is just plain pointer,
// so this is the case when you need to use free() or delete
delete strPointer;
I recommend to read something about smart pointers which are deleting the object they point to automatically. I'm getting pretty far from the original question but this topic is important to understand how C++ works.
You need to release attStr not the c++ string that will release its resources alone.
void func()
{
const char* attStr = strdup(OtherCharStr);
string str(attStr, strlen(attStr));
free(attStr);
}//here str will release its own resources
Also you can do
string str = OtherCharStr;
an that's it. Only check what happens with OtherCharStr
I am not going to past the whole source because it is 1000+ rows, but I have specially constructed a similar case about the matter I am interested in. Pay attention to this source code:
#include <iostream>
using namespace std;
class Person
{
public:
Person();
Person(char*);
~Person();
Person& operator=(const Person&);
friend Person& example(const Person&);
void print() const;
private:
char* name;
};
Person::Person()
{
name = new char[12];
name = "Temp";
}
Person::~Person()
{
delete[] name;
}
Person::Person(char* _name)
{
name = new char[strlen(_name)+1];
strcpy_s(name,strlen(_name)+1,_name);
}
Person& example()
{
char* TestName = new char[11];
TestName = "ShouldStay";
Person B(TestName);
return B;
}
void Person::print() const
{
cout << name;
}
int main()
{
example();
return 0;
}
In this case the example() function will return:
example returned {name=0x007cad88 "îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþ... } Person &
So obviously the destructor is called on the return command and delete the memory in the heap (so I am not able to do anything further with the pointer - it is pointing to already freed memory - no data).
My question is - How to avoid such behavior? What is the most elegant way to avoid such issue?
Thank you in advance!
Use string rather than char[] to avoid having to use new.
Return Person rather than Person&, as locally-scoped classes
are destroyed after they leave scope. Although this will cause a
copy to happen depending on compiler settings. This depends of course upon providing a proper copy constructor.
To guarantee avoiding a copy, change the signature of example to:
void example(Person& person)
And fill in the fields of the inputted person inside the function. The scope of that Person will be bound to the calling scope (or wherever else you constructed it). This method has drawbacks though such as you cannot chain the results together.
Your code contains many logical errors:
Person::Person()
{
name = new char[12];
name = "Temp";
}
In the above function you allocate a char array of 12 elements, then you simply forget about it and instead make name pointing to a string literal.
Person::~Person()
{
delete[] name;
}
whoopps. In case Person was build from a default constructor this would delete a string literal. A no-no in C++.
Person::Person(char* _name)
{
name = new char[strlen(_name)+1];
strcpy_s(name,strlen(_name)+1,_name);
}
Not 100% sure what strcpy_s is, but the code in this case allocates an array and seems to copy the string into the array. This seems ok (but just strcpy(name, _name); would have been better for many reasons).
Person& example()
{
char* TestName = new char[11];
TestName = "ShouldStay";
Person B(TestName);
return B;
}
This code is seriously broken. First of all it's returning by reference a temporary object. A Very Very Bad Idea. It's also allocating an array, and once again just forgetting about it and using a string literal instead.
The most elegant way (actually the ONLY way in my opinion) to get your code working is to first understand how the basics of C++ work. You should start first by reading a good C++ book from cover to cover, and only then you should start coding in C++.
Your 1000 lines of source code are most probably just rubbish. I'm not saying you're dumb, just that you don't know the basics of C++. Take care of them first by reading, not experimenting with a compiler.
You cannot learn C++ by experimenting for two reasons:
It's a complicate and sometimes even just downright illogical language because of its history. Guessing is almost always a bad move. No matter how smart you are there's no way you can guess correctly what a committee decided.
When you make a mistake there are no runtime error angels to tell you so. Quite often it happens that apparently the program works anyway... until it's run by your teacher, boss or spouse. Guessing C++ rules by writing code and observing what happens is nonsense.
Person& example()
{
char* TestName = new char[11];
TestName = "ShouldStay";
Person B(TestName);
return B;
}
The above creates an instance of Person on the stack, scoped to the function. So when the function returns, the destructor for Person is called and a reference to the destroyed object (on the stack) is returned.
In addition you should either consider returning a copy of Person, or you need to use the new operator to create an instance of person on the heap and return a pointer to that.
I have a program that has a memory leak and every time I add delete to my code it crashes. I am just wondering if anyone has any idea why this is happening. The code that crashes is below.
Here is the desturctor with the delete
the first and last name are declared as follows.
char* firstName;
char* lastName;
Name::~Name(){
delete[] firstName;
delete[] lastName;
}
and here is where the memory is allocated
Name::Name(Name& name){
//copys the first and last name from one Name to the other
firstName = new char [strlen(name.firstName)+1];
strcpy(firstName,name.firstName);
lastName = new char [strlen(name.lastName)+1];
strcpy(lastName,name.lastName);
}
Most likely you are assigning an object of your Name type at some point and there is no copy assignment (first I thought there is no copy constructor but you actually show your copy constructor). The default generated copy assignment just does a bitwise copy. As a result, you see a double delete[] of your pointers at some point (there is also a memory leak but this isn't as visible). Alternatively, how do your other constructors look like? Do have a default constructor possibly not initializing the pointers or a constructor which may end up storing pointers to string literals?
The best approach is not to use manual memory allocation but rather to use std::string. If you can't use std::string, e.g., because this is an assignment, I strongly recommend that you implement your own simple string class: dealing with multiple allocated entities without wrapping each individually into a suitable resource maintaining class is extremely hard. I can't do it correctly. Admittedly, I'm only programming in C++ since about 20 years.
For example, your copy constructor is not exception safe: if your second allocation throws an exception because there isn't enough memory to allocate, you have a resource leak. There are ways to deal with function-level try/catch blocks but it is much easier to use a string class: any fully constructed subobject is automatically destroyed if a constructor throws an exception. This way, the string's constructor takes care of the memory.
Assuming that firstName and lastName are proper elements of your Name class, you should take care that strlen doesn't check against NULL and so you should deal either with NULLs
Name::Name(const Name& name){
if (name.firstName) {
int len_z = strlen(name.firstName)+1;
firstName = new char [len_z];
strncpy(firstName, name.firstName, len_z);
// ^^^ also copy the terminator char ^^^
} else {
firstName = NULL;
}
// repeat for lastName:
if (name.lastName) {
int len_z = strlen(name.lastName)+1;
lastName = new char [len_z];
strncpy(lastName, name.lastName, len_z);
} else {
lastName = NULL;
}
}
or create standard Name objects with a constructor like this:
Name::Name() {
firstName = new char[1];
firstName[0] = '\0';
// repeat for lastName:
lastName = new char[1];
lastName[0] = '\0';
}
and at least here you see, why std::string is a much better choice: it's a class that implements all the aspects of strings you need. If you make this by hand, you have to double all of it for firstName and lastName ... and imagine there will a be soon a middleName in the next version of your Name class ...
I know this is very basic but somehow working on different technologies I have mashed up my C++ concepts
I have created a simple program but it is giving exception when the destructor is called.
Below is the code:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Employee
{
public:
Employee(char *name){
cout<<"Employee::ctor\n";
myName_p = new char(sizeof(strlen(name)));
myName_p = name;
}
void disp(){cout<<myName_p;}
~Employee()
{
cout<<"Employee:dtor\n\n";
delete myName_p;
}
private:
char *myName_p;
};
int main()
{
Employee emp("check");
emp.disp();
return(0);
}
Requesting all to clear this basic concept. As per my understanding we can't use delete[] because we are not using new[] in this case. Though I have tried using delete[] , but still it was giving error
You REALLY should use std::string here.
It is so much easier, especially for a beginner. The list of errors is:
you are calculating the wrong size of the name, it should be strlen(name)+1, not using sizeof anything.
You also should use new char[strlen(name)+1].
You are copying the data from the string supplied as the argument to the constructor, use strcpy rather than name_p = name - the latter leaks the memory you just allocated, and then you have a pointer to a const char * which you should not delete.
If you fix the allocation so that it is correct, you should then use delete [] name_p;.
However, it you instead use std::string, all of the above problems go away completely, you can just do:
Employee(char *name) name_p(name) { ... }
and get rid of all the problematic new, delete and copying. Of course, name_p is probably no longer a suitable name for the variable, but you get the idea.
Change
myName_p = new char(sizeof(strlen(name)));
myName_p = name;
to
myName_p = strdup(name);
and #include <cstring>. This creates new space and copies the parameter string. In this way, you'll have to call free instead of delete in your destructor.
Otherwise, after the second assignment, you have assigned the string literal "check" to myName_p, and the newly created space is discarded. Then your destructor tries to delete "check" rather than the allocated space, which results in crash.
Also, it is better practice to use std::string rather than old char* strings:
class Employee
{
public:
Employee(char *name): myName_p(name) {
cout<<"Employee::ctor\n";
}
void disp(){ cout << myName_p; }
private:
std::string myName_p;
};
The string class will manage memory for you.
pointer segfault problems...
I've been doing c++ for some weeks meanwhile but i ran again into that issue.
basically i have these classes given. I cant change them. I start with an instance of _ns3__importAuftragResponse kout;
class SOAP_CMAC _ns3__importAuftragResponse
{
public:
ns2__SOAPImportResult *return_;
...
class SOAP_CMAC ns2__SOAPImportResult
{
public:
bool *error;
int *numberOfIgnoreds;
....
My code needs to check for the numberOfIgnoreds
first approach
ns2__SOAPImportResult* imp_result;
imp_result = kout.return_;
int num;
num = *imp_result->numberOfIgnoreds;
or i use
ns2__SOAPImportResult imp_result;
imp_result = *(kout.return_);
int* num;
*num = *imp_result.numberOfIgnoreds;
I mostly get segmentation fault
I know generally what happens at runtime but cant come up with the correct ode. PLease help.
EDIT
made progress thx to your answer, Nawaz , but still need some understanding
ns2__SOAPImportResult * imp_ptr = new ns2__SOAPImportResult;
imp_ptr = kout.return_;
int * num = new (int);
// next line segfaults
*num = *imp_ptr->numberOfIgnoreds;
what's hard for me to understand is, how or why allocate memory for something that is already "there" as there is the member return_ of the object kout
So is it correct to say I need to allocate memory for the variable I assign it to (which is of same type of course)?
Most likely you've not allocated memory for the following members which you're using in the code you've quoted.
ns2__SOAPImportResult *return_; //in the class _ns3__importAuftragResponse
int *numberOfIgnoreds; //in the class ns2__SOAPImportResult
Other than this I don't see anything where things might go wrong!
Make sure you allocate memory for these members (and all other pointers in your program) before using them. You can use new to allocate memory. Or alternatively, you can use malloc() as well. Whatever you use, use it consistently, and deallocate the memory once you done, using delete or free() respectively!
This looks like gsoap. In that case you must use soap_malloc to allocate memory which you return.
For example on the FAQ page, you will find this example:
int ns__itoa(struct soap *soap, int i, char **a)
{ *a = (char*)soap_malloc(soap, 11);
sprintf(*a, "%d", i);
return SOAP_OK;
}