In My class I have a member variable;
QProcess* p1;
Inside some function, i initialize and use it as:
process1 = new QProcess();
it works fine. Now i have a situation where i have many of these processes to be started. One option is to declare all of them as member functions:
QProcess* p1;
QProcess* p2;
QProcess* p3;
...
And then initialize all of them when needed. However this is too much redundant work. So i tried to create a list and initialize it in a loop like this:
QList<QProcess*> procList;
for(int i=0; i<len; i++){
procList[i] = new QProcess();
}
It compiles fine but then crashes. Is there something missing or what am i doing wrong here?
I also tried to add all member variables in this list like:
for(int i=0; i<len; i++){
switch(i){
case 0:
procList[i] = p1;
break;
}
}
But this also has the same result like above
EDIT:
Based on your suggestion, i tried:
procList.append(new QProcess());
as well as procList.append(p1);
But result is same, it compiles but crashes at run time
EDIT:
So i found the issue was totally unrelated. The class itself where i was using this code (custom class i made) had no default constructor. And as i learned without default constructor, if you initialize a pointer, somehow it just crashes.... strange. After specifying default constructor it is working fine now.
You are accessing areas of the memory that is not allocated. Your list is empty and you access one element that is not valid.
As per documentation: https://doc.qt.io/qt-5/qlist.html#operator-5b-5d
T &QList::operator[](int i) Returns the item at index position i as a
modifiable reference. i must be a valid index position in the list
(i.e., 0 <= i < size()).
If this function is called on a list that is currently being shared,
it will trigger a copy of all elements. Otherwise, this function runs
in constant time. If you do not want to modify the list you should use
QList::at().
Try to use append or push_back, see https://doc.qt.io/qt-5/qlist.html#push_back
PS: Not an expert of QT, but you might want to look into a QList of std::unique_ptr to manage your memory if possible. Otherwise you risk to forget to delete the heap-allocated elements whose pointer is stored in the list.
Edit: OP reports that the suggestion did not work. I wrote a small example myself (disregarding possible leaks). The following example crashes when using operator[] but works with append in debug mode (I used QT creator for Windows with Qt 5.13.0 for MinGW 64 bits) . What OP is experiencing can be either some issue with the toolchain or some undefined behavior triggered before the append. I suggest OP tries to copy/paste my code in a clean project and run it.
#include <QList>
#include <QProcess>
int main()
{
QList<QProcess*> list;
for(int i = 0; i < 10; ++i){
QProcess * p = new QProcess();
//Decomment and crash
//list[i] = p;
//does not crash
list.append(p);
}
//Here you should cleanup
}
Related
I created a class and using multi-dimensional pointer as follows:
variable **v_mod;
v_mod = new variable *[3];
for(int i=0;i<3;i++)
{
v_mod[i] = new variable [n];
}
and deleting pointer after using
for( int i = 0 ; i < 3 ; i++ )
{
delete [] v_mod[i];
}
delete [] v_mod;
This is working perfectly fine but I am using many pointers. So can anyone help in writing a function in the class which helps in creating and deleting the pointers like
variable ** v_mod;
v_mod.create(3,n);
v_mod.delete();
and which works same way?
Don't use new use a vector:
vector<vector<variable>> v_mod(3, vector<variable>(n));
This will require that your variable object has a generated or your own default constructor.
But other than that you can use the vector version of v_mod as you used the dynamically allocated array version, except that a vector cleans itself up when it goes out of scope. So no need to delete.
EDIT:
#Hamza Anis has asked me how to do this without vector, so I'm updating this answer to reflect a couple ways to do that. Let me preface this by saying, vector is the right way to do this, anything short of vector is simply making life harder on everyone who handles the code.
Option 2 unique_ptr:
unique_ptr<variable[]> v_mod[3];
for(auto& i : v_mod) {
i = make_unique<variable[]>(n);
}
Option 3 only do this if it's a homework assignment:
variable* v_mod[3];
for(auto& i : v_mod) {
i = new variable[n];
}
for(auto& i : v_mod) {
delete[] i;
}
[Complex Example using ints]
Tutorials, searches, and the dim memory of my C++ formal education have left me clueless as to where I should use delete when I'm using a dynamically allocated object pointer in a loop, such as:
// necessary files are included, this code is within main
T * t;
t = foo.getNewT();
while (!t->isFinalT()) {
// print t stuff
delete t; // is this where I should delete t?
t = foo.getNewT();
}
delete t;
This lack of knowledge has become particularly troublesome on a recent class project. On my laptop (Linux Mint, g++ Ubuntu/Linaro 4.7.3-1ubuntu1) the code ran fine without the delete statement and crashed when I added the delete statement. On the school server (Solaris, g++ (GCC) 3.4.5), the code segfaulted after a few iterations without the delete statement, and runs fine when I add the delete statement.
How do I handle this kind of loop properly so that it will run in most environments?
Additional Info:
The error on my laptop occurs when the program reaches the delete request:
*** Error in 'program': free(): invalid next size (fast):...
Some of the other code:
// T.h
class T {
int id;
int num;
int strVarPos;
char * strVar;
public:
T();
~T();
// + misc. methods
}
// T.cpp
T::T() {
id = 0;
num = -1;
strVarPos = 0;
char * strVar = new char[11];
strVar[0] = '\0'
}
T::~T() {
delete [] strVar;
}
// Foo.cpp
T * Foo::getNewT() {
T * t = new T;
// populate T's fields
return t;
}
Resolution:
Because a simple test with just T * t and the loop worked ok, I ended up reconstructing the project starting from blank and adding one class at a time, to see when the problem would appear. Turns out that I had added additional content into a dynamically allocated array elsewhere in the program without updating the size constant I was using to initialize the array.
Evidently the school server could only handle the resulting memory discrepancy without crashing if I was making sure to delete the pointers properly (the program didn't run long enough to cause a significant memory leak in my tests), while my laptop wouldn't notice the memory discrepancy until I attempted to call delete (and then would crash).
Assuming that foo.getNewT() is handing ownership of the memory over to the caller:
T * t;
t = foo.getNewT();
//while (!t->isFinalT()) // if foo.getNewT ever returns NULL, this will be UB!!!
while (t != nullptr && !t->isFinalT())
{
// ...
delete t; // if you now own it and are no longer going to use it, yes, delete it here
t = foo.getNewT();
}
delete t; // you also need this one to delete the "final" t
However, you can avoid having to do it yourself by using std::unique_ptr:
std::unique_ptr<T> t;
t.reset(foo.getNewT());
while (t && !t->isFinalT())
{
// ...
t.reset(foo.getNewT());
}
Alternatively, you could rewrite the loop to flow a bit better:
std::unique_ptr<T> t;
do
{
t.reset(foo.getNewT());
if (t)
{
// do stuff with t
}
} while (t && !t->isFinalT());
the code ran fine without the delete statement and crashed when I
added the delete statement.
Are you sure getNewT is handing ownership of the T* to you? If you delete it, and then it tries to delete it later, you will end up with a heap corruption. If it is handing ownership over to the caller, and you do not delete it, you get a memory leak.
With the additional information in your edit:
char * strVar = new char[11];
That line is unnecessary if you declare strVar as either a std::string or a char[11]. If you attempt to copy any of those T objects, you'll be using the default copy constructor (as you have not defined one), which will do a shallow copy (that is, copy the value of the pointer for strVar). When you delete 2 Ts that are both pointing to the same memory location, you get a heap corruption. The most robust solution would be to declare strVar as a std::string.
The problem is not the delete. You have put it in the right place. It's more likely something else you are doing that is causing undefined behaviour.
Note that you should have a delete t after the loop as well (to catch the last one). This is assuming that foo.getNewT() always returns a valid pointer (which it must, because you never check if it is NULL).
You should delete a dynamically allocated memory when you no longer need it. If you want t to hold its value inside the for loop, then delete it outside the loop otherwise delete it inside.
However, the best thing to do is to use std::unique_ptr when you really have to use pointers . It will take care of deallocating the memory itself when all references to the memory are destroyed. You should try to avoid allocating memory as much as you can. Use STL containers if they fit the job.
I think when you delete t you are deleting the real object inside your structure.
Maybe that what is causing the problem.
I'm checking for memory leaks in my Qt program using QtCreator and Valgrind. I am deleting a few entries in a QHash in my destructor like this:
QHash<QString, QVariant*> m_Hash;
/**
* #brief
* Destruct a Foo Class instance
*/
Foo ::~Foo ()
{
// Do Cleanup here
// Delete hash leftovers
foreach( QString key, m_Hash.keys() )
{
qDebug() << "Deleting an entry..";
// Delete the hash item
delete m_Hash.take(key);
}
}
If I debug with Valgrind this code is fine and deletes the contents when the destructor is called:
>> Deleting an entry..
>> Deleting an entry..
If I launch with GDB within QtCreator, launch without GDB from QtCreator, or just run my Qt App from the command line I get Segmentation Faults!
Signal name :
SIGSEGV
Signal meaning :
Segmentation fault
If I commend out the 'delete' line then I can run my app just fine using any method but I do leak memory.
What gives? Does valgrind introduce some sort of delay that allows my destructor to work? How can I solve this?
hyde's answer is correct; however, the simplest possible way to clear your particular hash is as follows:
#include <QtAlgorithms>
Foo::~Foo()
{
qDeleteAll(m_Hash);
m_Hash.clear();
}
Note that the above technique would not work if the key of the hash table was a pointer (e.g. QHash<QString*, QVariant>).
You can not modify the container you iterate over with foreach. Use iterators instead. Correct code using method iterator QHash::erase ( iterator pos ):
QMap<QString, QVariant* >::iterator it = m_Hash.begin();
// auto it = m_Hash.begin(); // in C++11
while (it != m_Hash.end()) {
delete it.value();
it = m_Hash.erase(it);
}
Also, any particular reason why you are storing QVariant pointers, instead of values? QVariant is usually suitable for keeping as value, since most data you'd store in QVariant is either implicitly shared, or small.
The documentation does not explicitly mention it, but it is a problem that you are mutating the container you are iterating over.
The code to foreach is here.
Looking at the code, it and your code do basically the same as if you'd write:
for (QHash::iterator it=m_Hash.begin(), end=m_Hash.end();
it!=end;
++it)
{
delete m_Hash.take(key);
}
however, the take member function may trigger an invalidation of existing iterators (it and end), so your iterators might have become dangling, yielding undefined behavior.
Possible solutions:
* do not modify the container you iterator over while iterating
* make sure it is valid before the next iteration begins, and don't store an end-iterator (this solution forbids the use of foreach)
Maybe there is problem with the foreach keyword. Try replacing:
foreach( QString key, m_Hash.keys() )
{
qDebug() << "Deleting an entry..";
delete m_Hash.take(key); // take changes the m_Hash object
}
with:
for (QHash<QString, QVariant*>::iterator it = m_Hash.begin();
it != m_Hash.end(); ++it)
{
qDebug() << "Deleting an entry..";
delete it.value(); // we delete only what it.value() points to, but the
// m_Hash object remains intact.
}
m_Hash.clear();
This way the hash table remains unchanged while you iterate through it. It is possible that the foreach macro expands into a construct where you "delete the hashtable from under your feet". That is the macro probably creates an iterator, which becomes invalid or "dangling" as a side effect of calling
m_Hash.take(key);
I have a base class Toy and derived classes Toy_remote_car amd Toy_battery_car.
I am doing this:
Toy** ptr;
ptr=new Toy*;
ptr[0]=new Toy_remote_car[1];
ptr[1]=new Toy_battery_car[1];/*this is completely wrong according to my teacher because i never created ptr[1]. Instead this is a misuse of memory according to him.*/
The above code(ptr=new Toy*) is creating a single pointer of type Toy(ptr[0]) which contains the object of derived class Toy_remote_car.
Now i want to write such a code:
->the number of Toy type pointers should not be predefined.
->instead i would call an add_toy function which would create a ptr that will point to the type of object i want. Furthermore if i call the add_toy function again, it should not assign the data to the previos ptr, but it should create a new ptr. The following convention may help:
ptr[0]=new Toy_remote_car[1];
/*we want to add more toys so add_toy function called. A check is applied.*/
/*The check checks that ptr[0] already contains a value so it creates another pointer ptr[1]*/
ptr[1]=new Toy_battery_car[1];
->furthermore i would be able to access all the previous data. In short:
ptr[0]//contains one type of data.
ptr[1]//contains another type.
//and so on
->so it would automatically create a pointer(ptr) of type Toy whenever a new Toy is being added.
I hope i have explained well what i am trying to implement in this code.
Please please help me in this regard.
Thanks
Toy **ptr = new Toy *[n];
where n holds the number of Toy pointers you want. Growing the array is hard, but it can be done:
// Add x to toypp, an array of n pointers
// very stupid, linear-time algorithm
Toy **add_toy(Toy *x, Toy **toypp, size_t n)
{
Toy **new_toypp = new Toy*[n+1];
// copy the old array's contents
for (size_t i=0; i<n; i++)
new_toypp[i] = toypp[i];
toypp[n] = x;
// clean up
delete[] toypp;
return new_toypp;
}
Note the if the allocation fails, the old toypp and all pointers in it are not cleaned up. Really, if you want an array that grows, use a vector<Toy*> instead:
vector<Toy*> toy_ptrs(n);
and add toys with push_back.
Don't forget to delete every single Toy*, and with the first method, to delete[] the Toy**.
Handling various kinds of data can be done with inheritance.
I have come up with this code with a very simple logic. And this is working completely fine. Please give a look and do give opinions.
void add_toy_var()
{
temp=NULL;
temp=tptr;
tptr=NULL;
delete[] tptr;
C1.count1++;
tptr=new Toy*[C1.count1];
if(temp!=NULL)
{
for(int i=0; i<(C1.count1-1); i++)
{
tptr[i]=temp[i];
}
}
int choice2;
cout<<"Which Toy you want to add?"<<endl;
cout<<"1. Remote Toy Car"<<endl;
cout<<"2. Batt powered toy car"<<endl;
cout<<"3. Batt powered toy bike"<<endl;
cout<<"4. Remote control toy heli"<<endl;
cin>>choice2;
if(choice2==1)
{
tptr[C1.count1-1]=new Toy_car_rem[1];
tptr[C1.count1-1]->set_data();
}
else if(choice2==2)
{
tptr[C1.count1-1]=new Toy_car_batt[1];
tptr[C1.count1-1]->set_data();
}
else if(choice2==3)
{
tptr[C1.count1-1]=new Toy_bike_batt[1];
tptr[C1.count1-1]->set_data();
}
temp=NULL;
delete[] temp;
}
I'm compiling using Code::Blocks on Windows 7 using the MinGW compiler (which I can only assume is the latest version; both Code::Blocks and MinGW were installed this past week). My issue crops up under a particular circumstance, and my attempts to write a simpler script that demonstrates the problem have failed (which implies that there is something wrong with my structure). Also, my apologies for how long this post is.
Currently, I'm rolling with one class, FXSDL, which will act as an SDL wrapper:
class FXSDL
{
public:
FXSDL();
virtual ~FXSDL();
int Initialize();
int Render();
FXID CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims);
int SetAnim(FXID hRefID, FXID hAnimID);
FXID hPlayer;
protected:
private:
list<FXSurface> m_lstFXObjects;
list<FXSurface>::iterator m_liFirst;
SDL_Surface* m_lpsfSDLScreen;
Uint32 m_tmOld;
Uint32 m_tmFrame;
};
The value type of my list is:
struct FXSurface
{
FXID hRefID;
int wpxTile;
int hpxTile;
int wpxTotal;
int hpxTotal;
int cntTiles;
map<int, vector<int> > htAnims; // All animations
map<int, vector<int> >::iterator vCurr; // Currently active animation
vector<int>::iterator fiCurr; // Currently active frame
SDL_Surface* lpsfSDL;
SDL_Rect* lprcTiles; // Predefined frame positions
string* fpImage;
};
I've implemented very simple initialize and render function. The CreateCharacter function takes a few parameters, the most important of which is htAnims, a map of integer vectors (idea being: I define numeric ids with easy-to-remember representations, such as FXA_IDLE or FXA_WALK, as the key, and the series of number values representing frames for the animation as a vector). This could be fairly easily implemented as a multidimensional integer array, but animations are variable in length and I want to be able to add new anims (or redefine existing ones) without having to recast an array.
The CreateCharacter function is simple. It creates a new FXSurface, populates it with the required data, and pushes the new FXSurface onto the list:
FXID FXSDL::CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims)
{
//list<FXSurface>::iterator lpsfTemp;
FXSurface lpsfTemp;
list<FXSurface>::iterator lpsfPos;
SDL_Rect* lprcCurr = NULL;
int cntTileW = 0;
int cntTileH = 0;
int cntCurr = 0;
// Start off by initializing our container struct
//lpsfTemp = new FXSurface();
lpsfTemp.lpsfSDL = IMG_Load(fpImage.c_str()); // Try to load the requested image
if(lpsfTemp.lpsfSDL != NULL) // If we didn't fail to
{
// Assign some variables for tracking
lpsfTemp.hRefID = hRefID;
lpsfTemp.fpImage = &fpImage;
lpsfTemp.wpxTotal = lpsfTemp.lpsfSDL->w;
lpsfTemp.hpxTotal = lpsfTemp.lpsfSDL->h;
// If a tile width was specified, use it
if(wpxTile != 0)
{
lpsfTemp.wpxTile = wpxTile;
lpsfTemp.hpxTile = hpxTile;
} // Otherwise, assume one tile
else
{
lpsfTemp.wpxTile = lpsfTemp.wpxTotal;
lpsfTemp.hpxTile = lpsfTemp.hpxTotal;
}
// Determine the tiles per row and column for later
cntTileW = lpsfTemp.wpxTotal / lpsfTemp.wpxTile;
cntTileH = lpsfTemp.hpxTotal / lpsfTemp.hpxTile;
// And the total number of tiles
lpsfTemp.cntTiles = cntTileW * cntTileH;
lpsfTemp.lprcTiles = new SDL_Rect[cntTileW*cntTileH];
// So we don't calculate this every time, determine each frame's coordinates and store them
for(int h = 0; h < cntTileH; h++)
{
for(int w = 0; w < cntTileW; w++)
{
cntCurr = (h*cntTileW)+w;
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
}
}
// Now acquire our list of animations and set the default
//lpsfTemp.htAnims = new map<int, vector<int> >(*htAnims);
lpsfTemp.htAnims = htAnims;
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
this->m_lstFXObjects.push_back(lpsfTemp);
}
else
{
hRefID = 0;
}
return hRefID;
}
It is precisely as the object is pushed that the error occurs. I've stepped through the code numerous times. Initially, I was only able to tell that my iterators were unable to dereference to the FXSurface object. After using watches to identify the exact memory address that the iterator and list objects pointed to, and dereferencing the address, I noticed the reason for my segfaults: all the values which I put into the original FXSurface were pushed down two memory blocks when the list object copied it!
My process for doing this is simple. I set up a breakpoint at the return statement for CreateCharacter, which gives me a view of lpsfTemp (the FXSurface I later add to the list) and m_lstFXObjects (the list I add it to). I scroll through the members of m_lstFXObjects, which brings me to _M_node, which contains the memory address of the only object I have added so far. I add a watch to this address in the form of (FXSurface)-hex address here-
First, find the address:
(There should be a picture here showing the highlighted _M_node attribute containing the list item's address, but I can't post pictures, and I can only post one URL. The second one is by far more important. It's located at http://www.fauxsoup.net/so/address.jpg)
Next, we cast and deference the address. This image shows both lpsfTemp and the copy in m_lstFXObjects; notice the discrepancy?
http://www.fauxsoup.net/so/dereferenced.jpg - See? All the values are in the correct order, just offset by two listings
I had initially been storing fpImages as a char*, so I thought that may have been throwing things off, but now it's just a pointer and the problem persists. Perhaps this is due to the map<int, vector<int> > I store?
FXSDL has a destructor, but no copy constructor and no assignment operator. Yo you're using naked pointers, but violate the Rule of Three.
I'm not going to look any further.
Use smart pointers to manage resources. Do not put a naked resource into a type, except when that type's only intention is to manage this one resource. From another answer given yesterday:
As a rule of thumb: If you have to manually manage resources, wrap each into its own object.
At a glance, I'd say you're double-deleting lpsfSDL and/or lprcTiles. When you have raw pointers in your structure, you need to follow the rule-of-three (implement copy constructor, assignment operator, and destructor) to properly manage the memory.
These lines look wrong to me:
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
lpsfTemp.lprcTiles is a SDL_Rect*. lprcTemp.lprcTiles[cntCurr] is a SDL_Rect. You should be writing this, IMHO:
SDL_Rect tmpRect;
tmpRect.w = lpsfTemp.wpxTile;
tmpRect.h = lpsfTemp.hpxTile;
tmpRect.x = w*lpsfTemp.wpxTile;
tmpRect.y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = tmpRect;
Dump the lprcCurr entirely.
Now this code:
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
This is bad. These iterators are invalid as soon as the push_back completes. That push_back is making a copy of lpsfTemp. The map and vector members are going to copy themselves and those iterators will copy themselves but they will be pointing to lpsfTemp's members which are going to be destroyed as soon as CreateCharacter exits.
One way to fix that would be to push_back a FXSurface object at the beginning, use back() to get its reference and operate on that instead of lpsfTemp. Then the iterators would stay consistent and they should stay consistent since you are using a list which does not copy its objects around. If you were using a vector or deque or anything other than a list you would need to manage all those pointers and iterators in the copy constructor and assignment operator.
Another thing: Double and triple check your array bounds when you access that lprcTiles array. Any mistake there and you could be scribbling over who knows what.
I don't know if any of that will help you.