Destructor does not destroy objects - c++

I have written a small program, but main destructor is not working properly. Here is the code of the program:
#include<iostream.h>
class citizen {
private:
char* name;
char* nationality;
public:
citizen(char* name, char* nationality) {
this->name = name;
this->nationality = nationality;
}
citizen(const citizen &obj) {
name = obj.name;
nationality = obj.nationality;
}
void display() {
cout << "Name: " << name << endl;
cout << "Nationality: " << nationality << endl;
}
~citizen() {
if(name){
delete[]name;
}
if(nationality) {
delete []nationality;
}
}
};
main() {
citizen obj1("Ali", "Pakistani");
obj1.display();
{
citizen obj2 = obj1;
}
obj1.display();
system("pause");
}
What I know is that in main function where I'm assigning state of obj1 to obj2, from that place both of them are now pointing to same memory area. Whereas the code citizen obj2 = obj1; is between two curly braces.
{
citizen obj2 = obj1;
}
So after execution of second curly brace, obj2 should destroy and also delete variables name and nationality. And when I call obj1.display(); for the second time it should display garbage on the screen.
But obj1 is still printing exact name which I have provided in constructor, even though it shouldn't be.
Please explain this behavior.

Your delete[]s invoke undefined behavior because you're attempting to destroy string literals. Anything can happen.
Even if you allocated memory yourself, you'd still run into undefined behavior because you'd be attempting to access memory you've already deleted:
obj1.display();
{
citizen obj2 = obj1;
}
obj1.display(); // ILLEGAL
Because you didn't define an assignment operator, the compiler-generated one will be used, which just assigns the pointers to the same memory - memory which you destroy and then attempt to access.

This code is faulty.
if(name){
delete[]name;
}
if(nationality){
delete []nationality;
}
You are deleting, something which you have not allocated on heap, using the new operator.

Your copy constructor just copies the pointers (as the implicit one would do, if you hadn't provided your own), meaning that both objects will try to delete the same arrays. Additionally, you're setting the pointers to point to string literals, which must not be deleted at all; you must only delete objects that you created with new. The simple solution is to delegate memory management to a class designed to do that correctly:
std::string name;
std::string nationality;
Now you don't need to bother with your own destructor, copy constructor or copy-assignment operator; and as a bonus, your class will also be correctly movable in C++11.
If you enjoy dealing with memory issues yourself, then you'll need your constructors to allocate new buffers and copy the contents across. Be careful with exception safety, since you're trying to juggle two separate dynamic resources in one class, which is invariably a recipe for errors. You'll also need a copy-assignment operator (per the Rule of Three), and for efficiency you might also consider a move constructor and move-assignment operator.
Also, it might be worth updating to one of this century's versions of the language. <iostream.h> hasn't been a standard header for about fifteen years.

Others have pointed out the string related error but I think you're making a much more fundamental mistake: delete does not destroy things*; it merely frees up the memory for reuse and calls the relevant destructor. This means that its often entirely possible to use deleted objects after the delete operation without getting garbage back.
*- On some implementations, in __DEBUG mode it will stamp on released memory to allow you to spot these errors but this isn't part of the standard.

you should only delete block of memory that was dynamically allocated in the class using new operator
citizen(char* aname, char* anationality){
size_t nameSize = strlen(aname)
size_t nationalitySize = strlen(anationality)
this->name = new char[nameSize];
this->nationality = new char[nationalitySize];
strcpy(this->name, aname, nameSize);
this->name[nameSize ] = NULL;
strcpy(this->nationality , anationality , nationalitySize);
this->nationality [nationalitySize] = NULL;
}
if you create a memory in constructor, then you delete them in destructor.
and because you have some assignment, then you should implement a copy constructor, WHICH create a memory and copy the data on the right side of the = operator
final thought, you are better off using a string object if you cant deal with pointers to avoid memory leaks

It's pure luck that your second display call works.
As Jack Aidley points out, delete does not literally delete the values, just marks the memory region as usable. Thus, if no other application allocates and modifies that freed region, the previous values may stay there. Furthermore, after the deletion you still keep the pointers to that addresses.
In summary, you're accessing the same memory region having old values in it. But it's just luck because that region didn't modified by anybody.
To prevent these kinds of errors, you should always assign NULL to the unused pointers so that next time you get Access Violation error when you try to access them. Some compilers (such as MSVC) rewrite the freed memory with a signature value (such as 0xDDDDDD) so that during debugging you can catch the problems easily. Check this answer for details
Finally, delete should match to new otherwise the behavior is undefined so it's again just luck. I can't even run your application and display results. It keeps crashing and giving memory errors.

Thanks everybody. I have replace this code of constructor
citizen(char* name, char* nationality) {
this->name = name;
this->nationality = nationality;
}
with this code
citizen(char* name, char* nationality){
this->name = new char[strlen(name)+1];
strcpy(this->name, name);
this->nationality = new char[strlen(nationality)+1];
strcpy(this->nationality, nationality);
}
and finally it works fine. thanks

Related

Deleting a dynamically allocated array from a function that initiates it C++

I'm writing a program in C++ that has to use dynamically allocated arrays from various structures (in separate files). A lot of times, I need to initiate these arrays inside of a function. Usually after initiating them, I write data to the array of a structure, or even an array inside of an array of structures, and then use the data later on. Therefore I don't use delete inside of the function.
For example, here is one of the structures that I use, a student structure:
struct Student {
int id; // student ID
char gradeOption; // either G or P
double totalScore;
std::string studentName;
int* rawScores = NULL; // array that holds raw scores for a student
// if no scores are entered for a specific ID, we check for NULL
// we can then set the scores to 0
std::string* finalGrade; // final grade given in course
};
And here is the function to input raw scores.
// input raw scores for each id
void inputRawScores(int gradedArtifacts, int id, Student* student) {
student[id].rawScores = new int[gradedArtifacts];
for(int i = 0; i < gradedArtifacts; i++) {
std::cin >> student[id].rawScores[i];
}
}
In my driver file, students also gets initialized with a value. Shown here:
Student* students = new Student[numOfStudents]; // array of students
The problem is is that I use these raw scores, and the array of students for calculations in a separate file, and use them for output in other files, and in other methods. How would I go about deleting any of these?
Also I realize that using delete will delete the structure and the pointers inside of the structure, but not the objects that the pointers point to. So I'm assuming this ties back into the first question and I can't just issue a delete at the end of my program.
Edit: I'm sorry, as many others have pointed out I should have stated the restraints that I have on the project. I'm not allowed to uses: classes, vectors, functions inside of structs (like constructors, destructors).
Don't do that.
Your system is badly designed, your struct should be a class and internally handle the rawScores memory - using a std::vector would be the easiest part, but even if you use regular pointers, the key is that the information about how many there are, and where they are stored, should be tracked in a class.
In other words, the student structure should keep track of HOW MANY elements there are, and allocate/deallocate the memory as needed. It should not be done in the function inputRawScores - that function may well call the function for setNumRawScores and call the function for setRawScore(n, value), but not allocate memory in the reader function. That belongs as a member function in the student structure. Then introduce a destructor method for your student, that is responsible for deallocating the memory.
Of course, using std::vector will "hide" all this from you, and you just have to set the size (or use push_back).
Given your newly posted constraints, I think you could just implement a deletion-function to traverse through the Student array and do manual cleanup.
First, we create a function that deletes the dynamic objects of one single student. Note that we could have used Student&as the parameter type, but given the information in your question I am not sure if you have learned references yet, or if you are allowed to use them. So we stick with the pointer:
void cleanupStudent(Student* student) {
delete[] student->rawScores;
delete student->finalGrade;
// EDIT: Setting pointers back to NULL after deletion provides
// some improved safety and is good practice.
student->rawScores = NULL;
student->finalGrade = NULL;
}
After that we create a function that allows you to delete the complete Student array by looping through all the items in the array and calling the cleanup function:
void deleteStudents(Student* students, int studentCount) {
for(int i = 0; i < studentCount; i++) {
cleanupStudent(&students[i]);
}
delete[] students;
}
Here, please note the ampersand-symbol (&students[i]) which we require to get a pointer to the object (which is required as a parameter to the cleanup function). After that, the student array itself is deleted.
You can call these functions like this:
int numOfStudents = 16;
Student* students = new Student[numOfStudents];
deleteStudents(students, numOfStudents);
Or with a single student:
Student* student = new Student;
cleanupStudent(student);
delete student;
As you might have noticed we sometimes use delete and sometimes delete[]. The first one just deallocates memory that has been allocated with new. The latter does the same thing to memory that has been allocated with new[]. This is very important to get right, otherwise you will get runtime errors. Also, make always sure that EVERY pointer in your struct is initialized wih NULL (C) or nullptr (C++).
Since it seems that you are just learning C/C++ it is crucial to mention that the above code is very unsafe, and you could get into real problems if e.g. the studentCount is not matching the actual number of items in the array. But for now I guess you wouldn't know (or aren't allowed) to do better.
EDIT: I noticed that your finalGrade member is of type std::string*. Is there a reason for this to be a pointer? Because if you just want to store a string, you can just do a std::string, no reason there to be a pointer. Please don't confuse a C-String of type char* with a STL string std::string.
This answer is obsolete since the owner of this questions specified some constraints that do not allow constructors/destructors.
As far as I unterstand your question, you do not know how to delete the actual dynamically allocated rawScores and finalGrad objects in your Student object, right? If so, the answer is quite simple, you just use a Destructor:
struct Student {
int id; // student ID
char gradeOption; // either G or P
double totalScore;
std::string studentName;
int* rawScores = nullptr;
std::string* finalGrade = nullptr;
// Disable copy and move assignment
Student& operator=(const Student& rhs) = delete;
Student& operator=(Student&& rhs) = delete;
// Disable copy and move construction
Student(const Student& rhs) = delete;
Student(Student&& rhs) = delete;
Student() {
// Initialize members.
}
// Destructor
~Student() {
delete[] rawScores;
delete finalGrade;
}
};
As soon as you deallocate a Student object using the delete operator:
Student* students = new Student[numOfStudents];
delete[] students; // <-- deallocation
The destructor is called for each object, which in turn will delete the dynamically allocated objects inside.
You don't have to bother if the pointers are NULL or not, calling delete on a pointer that is NULL is valid. Also, please initialize ALL pointers initially with nullptr when constructing the object (as shown above).
As long as you are not mixing runtimes accross different EXE/DLL boundaries you can delete the Student array from anywhere in your program, not matter in which file you allocate/deallocate it.
I hope this answers your question. If not, please be more specific about the problem you have.
EDIT: As pointed out in the comments, you should disable copy/move semantics if you are doing it this way (or implement them). But disabling them would practically pin you to dynamic allocation of the Student struct and give you less flexibility with most of the STL containers. Otherwise you could also use an std::vector instead of dynamically allocated arrays as pointed out in the other anwers.
It would be very tedious to effectively delete everything you hve allocated using new in this case as you are passing pointers to other modules/functions.
You have two options over here:-
Either replace those dynamic arrays ( rawscores/finalGrade ) with corresponding vectors.
You can use smart pointers ( I think auto_ptr would suffice if you are not using containers ) to take care of memory mangement.
EDIT:-
One main issue you have to handle if you are creating raw student pointer is of ownership. Let's say you have allocated memory to Student* and then you are passing this object to several modules/functions. You need to take into account that you don't call delete when your pointer is still in use in some other module. Also it should also not call delete when it's already deleted in some module. That's why I pointed you to two options...

C++ / destructor - operator delete

I was wondering if I have to delete this pointer in example like this :
class Person
{
public:
Person(char *name) :_name(name) {}
// Is this delete necessary?
~Person() {
cout<<"Godbay Person"<<endl;
delete _name;
}
private:
char * _name;
}
This is pretty surely wrong in any case.
There are two possibilities:
The name is created on the free store exclusively for your object, and your object has to assume ownership. Then the name has to be deleted.
The name is not created on the free store (e.g. as a string litaral, which is quite possible), or some other object is managing the name, so your object should not assume ownership. Then any deletion would wreak havoc with your program.
So why do I say its wrong even in the first case? Because name sounds like a string, not a single character, wich means name* will point to an dynamically alocated array of characters. In that case, the correct way to delete it would be delete[] name.
But: If possible, avoid using plain (char) pointers, for case 1. Use some memory management class instead (a string class or smartpointers), to get rid of the headaches of manually managing memory ownership. delete and delete[] should appear only seldom in your code except if you don't have access to up-to-date C++ compilers.
It is a matter of who owns the allocated memory, in this case it looks like Person is not owning it so then no, so there is no need to delete. Using raw pointers like you do in Person always give rise to questions about ownership, that is why it is recommended to use shared_ptr/unique_ptr instead or even better std::string since it seems to be a string.
Generally, you have to call delete each time you create a pointer with new.
It depends on creation procedure.
In this case no:
Person *p = new Person("John");
In this case yes:
char *str = new char[32];
::strcpy(str, "John");
Person *p = new Person(str);
In this case yes, but with ::free function rather than operator delete.
char *str = (char *)::malloc(32);
::strcpy(str, "John");
Person *p = new Person(str);
Consider using std::string instead of C string pointer.

Using copy constructor and copy assignment operator for pointers to dynamically allocated memory

I was looking at an explanation of the Rule of Three, and found the following code:
// 1. copy constructor
person(const person& that)
{
name = new char[strlen(that.name) + 1];
strcpy(name, that.name);
age = that.age;
}
// 2. copy assignment operator
person& operator=(const person& that)
{
if (this != &that)
{
delete[] name;
// This is a dangerous point in the flow of execution!
// We have temporarily invalidated the class invariants,
// and the next statement might throw an exception,
// leaving the object in an invalid state :(
name = new char[strlen(that.name) + 1];
strcpy(name, that.name);
age = that.age;
}
return *this;
}
explaining things (found here: What is The Rule of Three?)
I wasn't sure if I should ask the question there (since it's been a while since it was posted) or to make a new question, so I hope I don't get in trouble. I just want to see if I understood this code correctly?
From what I'm understanding here is that instead of copying the pointers (and thus having two objects point to the same memory), the object being copied to is dynamically allocating new memory which will then contain the same data that the object that was copy contains? And what is the reason that the copy assignment operator function has "delete [] name]" at the beginning? Is it because when = is used, the pointer is automatically copied and thus this new object points to the same memory as the object copied, and delete [] name deletes that memory before dynamically allocating new memory for it to point to? Actually, I'm not really sure what I'm saying so can somebody explain to me why it uses delete? And finally, what is the purpose of the if (this != &that) part?
Thanks!
The point of the delete is to free the memory previously owned by the this object for the name field. Notice that this is the assignment operator overloading, i.e:
A x,y;
x = y;
Would call the function with this == &x and that == &y.
This copies y's inner members to x while making sure to free any dynamically allocated memory previously allocated to x.name
The member variable name is a pointer. It (almost always) points to a char[] that was allocated on the heap (that is, with new).
We want to copy the name of the other object to this one:
strcpy(name, that.name);
But before that we must make sure that the array which name points to is big enough to hold the new name (and a terminating '\0'), so we allocate space with new:
name = new char[strlen(that.name) + 1];
But what about the space that name previously pointed to? We don't want to just abandon it, that would be a memory leak, so we should delete it before reassigning the pointer:
delete[] name;
As for this != &that, consider what would happen if some careless person used the assignment operator from one person to itself (Alice = Alice). Work through the steps and you'll see that the name would be entirely lost.
First off, this assignment operator is a bad example! In particular it is not thread-safe! If you want to write a proper assignment operator, you write it like this:
person& operator=(person other) {
other.swap(*this);
return this;
}
where swap() is a member function you want anyway, simply swapping all members:
void swap(person& other) {
std::swap(this->name, other.name);
std::swap(this->age, other.age);
}
With respect to your questions:
The check if (this != &that) is helpfully put in by the author to indicate that the code is wrong! There are basically two cases why it is wrong:
The idea of this comparison is to guard against self-assignment. If the code following this check actually depends on this check being present to be correct, it is almost certainly not exception safe (rarely, the code afterwards provides the basic guarantee; I have never seen an example where it ends up implementing the strong exception safety guarantee although there is no reason for the assignment operator to not implement the strong exception safety guarantee).
If the code is just there and not strictly needed it is "optimizing" the self-assignment case. ... and impacting all cases where where the assignment is not a self-assignment which is, hopefully, the vast majority! If your code is mostly busy assigning objects to themselves, there is something more fundamental broken in the code.
C++ doesn't have any garbage collection: If you allocated memory, you need to release memory (the same is, of course, true for all other resources). There are two forms to allocate memory in C++ using new:
You can allocate individual objects using new T(args) or new T{args} where T is not a typedef for an array type, and args is a placeholder for the constructor arguments. Memory thus allocated needs to be release using delete ptr where ptr is the result returned from the expression above. Typically, the memory is not release explicitly but passed to an object which takes care of releasing the memory, e.g., std::unique_ptr<T>(new T(args)): the destructor of std::unique_ptr<T> will call delete as needed.
You can allocate an array object, typically using new T[n] where n is the size of the array. Objects thus allocated need to be released using delete[] array where array is the result returned from the array allocation. This is rarely seen as normally you'd rather use std::string or std::vector<T> to allocate arrays. You can also use the class template mentioned above but you need to indicate that you need to release an array: std::unique_ptr<T[]>(new T[n]).
The reason for delete[] name; is that the class invariant is that name points to a dynamically allocated buffer sized exactly for the person's name. Notice that we're about to create a new buffer to accommodate our copy of the data stored in that.name. If we didn't delete[] what our original name was pointing to, we'd leak that memory.
As for if (this != &that), simply mentally trace what would happen if this wasn't there and someone called x = x on a person x object. First, we delete[] name. Since this == &that, this also means this->name == that.name, so we've invalidated the buffer pointed to by that.name as well. In the next step, we call strlen() on the (now invalidated) buffer, which gives Undefined Behaviour (could be e.g. a segfault).

Double free or corruption after queue::push

#include <queue>
using namespace std;
class Test{
int *myArray;
public:
Test(){
myArray = new int[10];
}
~Test(){
delete[] myArray;
}
};
int main(){
queue<Test> q
Test t;
q.push(t);
}
After I run this, I get a runtime error "double free or corruption". If I get rid of the destructor content (the delete) it works fine. What's wrong?
Let's talk about copying objects in C++.
Test t;, calls the default constructor, which allocates a new array of integers. This is fine, and your expected behavior.
Trouble comes when you push t into your queue using q.push(t). If you're familiar with Java, C#, or almost any other object-oriented language, you might expect the object you created earler to be added to the queue, but C++ doesn't work that way.
When we take a look at std::queue::push method, we see that the element that gets added to the queue is "initialized to a copy of x." It's actually a brand new object that uses the copy constructor to duplicate every member of your original Test object to make a new Test.
Your C++ compiler generates a copy constructor for you by default! That's pretty handy, but causes problems with pointer members. In your example, remember that int *myArray is just a memory address; when the value of myArray is copied from the old object to the new one, you'll now have two objects pointing to the same array in memory. This isn't intrinsically bad, but the destructor will then try to delete the same array twice, hence the "double free or corruption" runtime error.
How do I fix it?
The first step is to implement a copy constructor, which can safely copy the data from one object to another. For simplicity, it could look something like this:
Test(const Test& other){
myArray = new int[10];
memcpy( myArray, other.myArray, 10 );
}
Now when you're copying Test objects, a new array will be allocated for the new object, and the values of the array will be copied as well.
We're not completely out trouble yet, though. There's another method that the compiler generates for you that could lead to similar problems - assignment. The difference is that with assignment, we already have an existing object whose memory needs to be managed appropriately. Here's a basic assignment operator implementation:
Test& operator= (const Test& other){
if (this != &other) {
memcpy( myArray, other.myArray, 10 );
}
return *this;
}
The important part here is that we're copying the data from the other array into this object's array, keeping each object's memory separate. We also have a check for self-assignment; otherwise, we'd be copying from ourselves to ourselves, which may throw an error (not sure what it's supposed to do). If we were deleting and allocating more memory, the self-assignment check prevents us from deleting memory from which we need to copy.
The problem is that your class contains a managed RAW pointer but does not implement the rule of three (five in C++11). As a result you are getting (expectedly) a double delete because of copying.
If you are learning you should learn how to implement the rule of three (five). But that is not the correct solution to this problem. You should be using standard container objects rather than try to manage your own internal container. The exact container will depend on what you are trying to do but std::vector is a good default (and you can change afterwords if it is not opimal).
#include <queue>
#include <vector>
class Test{
std::vector<int> myArray;
public:
Test(): myArray(10){
}
};
int main(){
queue<Test> q
Test t;
q.push(t);
}
The reason you should use a standard container is the separation of concerns. Your class should be concerned with either business logic or resource management (not both). Assuming Test is some class you are using to maintain some state about your program then it is business logic and it should not be doing resource management. If on the other hand Test is supposed to manage an array then you probably need to learn more about what is available inside the standard library.
You are getting double free or corruption because first destructor is for object q in this case the memory allocated by new will be free.Next time when detructor will be called for object t at that time the memory is already free (done for q) hence when in destructor delete[] myArray; will execute it will throw double free or corruption.
The reason is that both object sharing the same memory so define \copy, assignment, and equal operator as mentioned in above answer.
You need to define a copy constructor, assignment, operator.
class Test {
Test(const Test &that); //Copy constructor
Test& operator= (const Test &rhs); //assignment operator
}
Your copy that is pushed on the queue is pointing to the same memory your original is. When the first is destructed, it deletes the memory. The second destructs and tries to delete the same memory.
You can also try to check null before delete such that
if(myArray) { delete[] myArray; myArray = NULL; }
or you can define all delete operations ina safe manner like this:
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p) { delete (p); (p) = NULL; } }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p) = NULL; } }
#endif
and then use
SAFE_DELETE_ARRAY(myArray);
Um, shouldn't the destructor be calling delete, rather than delete[]?

Memory leak with std::string when using std::list<std::string>

I'm working with std::list<std::string> in my current project. But there is a memory leak somewhere connected with this. So I've tested the problematic code separately:
#include <iostream>
#include <string>
#include <list>
class Line {
public:
Line();
~Line();
std::string* mString;
};
Line::Line() {
mString = new std::string("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
}
Line::~Line() {
//mString->clear(); // should not be neccessary
delete mString;
}
int main(int argc, char** argv)
{
// no memory leak
while (1==1) {
std::string *test = new std::string("XXXXXXXXXXXXXXXXXXXXXXXX");
delete test;
}
// LEAK!
// This causes a memory overflow, because the string thats added
// to the list is not deleted when the list is deleted.
while (1==1) {
std::list<std::string> *sl = new std::list<std::string>;
std::string *s = new std::string("XXXXXXXXXXXXXXXXXXXXXXX");
sl->push_back(*s);
//sl->pop_back(); //doesn't delete the string?- just the pointer
delete sl;
}
// LEAK!
// Here the string IS deleted, but the memory does still fill up
// but slower
while (1==1) {
std::list<Line> *sl = new std::list<Line>;
Line *s = new Line();
sl->push_back(*s);
//sl->pop_back(); //does delete the Line-Element
sl->clear();
delete sl;
}
return 0;
// this does not cause any noticable memory leak
while (1==1) {
std::list<int> *sl = new std::list<int>;
int i = 0xFFFF;
sl->push_back(i);
sl->clear();
delete sl;
}
return 0;
// This does not cause any overflow or leak
while (1==1) {
int *i;
i= new int [9999];
delete[] i;
}
}
Why does my string list cause a memory leak? Shouldn't deleting the list cause the destructors to be called on each contained string?
In the first case, the list class has no idea you allocated the string with new, and cannot delete it. In particular, the list only ever contains a copy of the string that you passed in.
Similarly, in the second case, you never free the line object s, and thus you leak memory. The reason why the internal string is deleted is because you have not correctly implemented a copy constructor. Thus, if you make a copy of a Line object, both of them will reference the same string pointer, and if you try to delete both of them, you are in trouble.
Your Line class needs a copy-ctor and an assignment operator that properly deal with the string pointer.
Alternatively, just have a std::string member rather than a pointer and let the string class handle the memory (that's what it's for).
Here's your leak:
while (1==1) {
std::list<Line> *sl = new std::list<Line>;
Line *s = new Line();
sl->push_back(*s);
//sl->pop_back(); //does delete the Line-Element
sl->clear();
delete sl;
}
STL collections store elements by value, allocating and releasing space for it. What you allocated you have to release explicitly. Just add delete s to the end of the loop.
If you have to store pointers, consider storing managed pointers like boost::shared_ptr, or look into Boost pointer container library.
On the second look, you don't need to allocate Line on the heap at all. Just change it to:
sl->push_back(Line());
And, as others noted, make sure Line's pointer members are properly managed in copy-constructor, copy-assignment, and destructor.
std::list<Line> *sl = new std::list<Line>;
Line *s = new Line();
sl->push_back(*s);
//sl->pop_back(); //does delete the Line-Element
sl->clear();
delete sl;
You forgot to delete s . You new'ed it, you have to delete it. As you're copying objects around(By stuffing them in a list) while managing memory in your Line class, you also have to provide a copy constructor and assignment operator for your Line class.
Others have addressed specifically why you have your leak - deleting a list of pointers does not delete the objects that are pointed to, and should not as a simple pointer gives no indication whether it was the only reference to that object ), but there are more ways than having to make sure you iterate the list on deletion to delete the pointers.
As far as the example here shows theres no reason to use pointers to anything at all, since you're using them when they enter the scope and discarding them when they leave the scope - simply create everything on the stack instead and the compiler will properly dispose of everything on exiting the scopes. Eg.
while (1==1) {
std::list<std::string> sl;
std::string s = std::string("XXXXXXXXXXXXXXXXXXXXXXX");
sl.push_back(s);
}
If you do need the pointer behaviour (to avoid having to duplicate objects that are linked to by many things etc. etc.) you should take a look at smart pointers, as these will remove many of the pitfalls as they can automatically handle the reference counting and semantics you require. (Specifically take a look at the boost smart pointers)
There are many types of smart pointer you can use depending on specific need and ownership semantic to represent.
The std::auto_ptr has strict ownership - if the pointer is "copied" the original is nulled and ownership transfered - there is only ever be one valid auto_ptr to the object. The object pointed to is deleted whenever the smart pointer with ownership goes out of scope.
Theres also boost shared pointers and weak pointers using reference counting to know when to free the object being pointed to. With Shared pointers each copy of the pointer increases a reference count, and the object pointed to is deleted whenever all the shared pointers go out of scope. A weak pointer points to an object managed by a shared pointer but does not increase the reference count, if all the parent shared pointers are deleted attempting to dereference a weak pointer will throw an easily catchable exception.
Obviously theres a lot more to the range of smart pointers, but I highly suggest taking a look at them as a solution to help with managing your memory.