I am writing q Qt5/C++ program with the following types:
struct SSensorScore {
Types::EScoreComparisons comparisonType;
ESensorValueTypes comparisonValueType;
QVariant comparisonValue;
};
typedef QList<SSensorScore> TSensorScoreList;
TSensorScoreList scoreList;
I append items to my scoreList list this:
SSensorScore *newScore = new Types::SSensorScore;
newScore->comparisonType = comparisonType;
newScore->comparisonValueType = Types::ESensorValueTypeUnknown;
newScore->comparisonValue = QVariant(config_score);
scoreList.append(*newScore);
and I remove them like this:
foreach (Types::SSensorScore score, scoreList) delete &score;
Is there something wrong with doing the above? When compiling the last line (delete the struct) gives me an error that 'the address of score will never be null'. So what? I must be missing the point of the warning...
Perhaps I'm confused about how to create a QList of dynamically created structs. Do I need to change my QList to a list of pointers? Do I need to cast my score so that delete knows it's dynamically created?
You have memory leak and undefine behaviour! :
scoreList.append(*newScore);
this line is going to copy the *newScore and then append it to scoreList. so you will leak newScore.
and this line :
foreach (Types::SSensorScore score, scoreList)
delete &score;
It will delete the the copy of object so it's undefine behaviour.
and also Qt make a copy of container before entering foreach . so even if you fix the first problem still it won't delete anything!
just change your code to :
SSensorScore newScore;
newScore.comparisonType = comparisonType;
newScore.comparisonValueType = Types::ESensorValueTypeUnknown;
newScore.comparisonValue = QVariant(config_score);
scoreList.append(newScore);
and you won't have to delete your list's item using that foreach.
Related
I have a QList and I'm trying to replace the objects in the list with new objects. The context is that I have a list of custom objects (the class name is "Conversation") to represent a list of group chats in a messaging platform. I use std::find_if to iterate through the list of pointers to find one with the right ID, and I want to take the pointer to that found object, deallocate it (delete?), and reassign that pointer to point at an object I generate with the "new" keyword. I think I'm doing this right but I'm not sure how to verify.
I tried a couple different iterations, ran into some issues where I realized I was using a const_iterator rather than just an iterator, so I couldn't modify any data. But I've fixed that and it seems like it's working, but I'm not positive.
Here's what I've got:
GroupChat *gc = new GroupChat(); // extends Conversation
// ...I update the member data here...
auto foundChat = std::find_if(conversations_.Conversations.begin2(),
conversations_.Conversations.end2(),
[this, gc](Conversation* o) { // my code to find the correct one...
}
if (foundChat != conversations_.Conversations.end()) {
auto c = (*foundChat);
delete c; // Is this right? Not positive...
//*foundChat = nullptr; // do I need this?
c = gc;
}
It seems like it's working but I'm worried about dangling pointers and incorrect memory deallocation/allocation. Could someone spot check me on this? Thanks for any help!
I have a data structure defined up here called this:
typedef list <classSpec*> ClassSpecList;
I'm trying to add stuff into the list here based on functions that return certain values of that match the same data type. In one function, I have a list pointer object defined here and I have another statement that calls a function.
ClassSpecList *answer = 0;
classSpec *thisanswer = parseClass(br);
Basically I'm trying to add the results of what thisanswer returns into my main ClassSpecList. Problem is, when I try
answer->push_back(new classSpec (*thisanswer));
It compiles but I get a seg fault
When I try somethign else like:
answer->insert(ClassSpecList.begin(), *thisanswer);
I keep getting primary expression errors and I do not know why. I even tried it with other list made without typedef and I still get those.
Thank you.
You should initialize the pointer answer first, like :
ClassSpecList *answer = new ClassSpecList;
then you can add thisAnswer into this list.
This should work:
ClassSpecList *answer = new ClassSpecList;
answer->push_back(thisAnswer);
as should this, which is usually recommended:
ClassSpecList answer;
answer.push_back(thisAnswer);
If possible, parseClass shouldn't return a pointer, and you should use typedef list <classSpec> ClassSpecList;.
I recently started with C++ and i'm not entirely sure I grasp the concept of pointers and their connection to arrays. I have two classes, Term and Polynom. I have a main loop which allows the user to enter 2 numbers. Those numbers is then added to the "Term" object and that object is then added to the "Polynom" object. Everytime the loop is executed a new "Term" object is created.
//These lines are executed until the user is done entering numbers
potens = new Term;
potens->sattPotens(kinput, ninput);//Add values to "Term object"
poly.addTerm(potens);//Add "Term" object to "Polynom" object
A "Polynom" object is only created once in the program. In the "Polynom" class I use a "Term" pointer to store all the "Term" objects that is added to the "Polynom" object. The "Term" pointer in the "Polynom" class is initiated once in the "Polynom" constructor.
void Polynom::addTerm(Term *t){
*(term+antal_termer) = *t;//This is were the program crashes
antal_termer++;
}
I know I could use a vector instead of a pointer to store the "Term" objects but i'm trying to learn how pointers work. I am also unsure when I'm supposed to delete the objects created in the main loop. Since every time the loop is executed I create a new "Term" object but I never delete them.
EDIT: I used to allocate the "Term" object in the "Polynom" class this way: term = new Term[]; I then changed it to term = new Term[10]; but I still crashes when I execute term[antal_termer] = *t;
*(term+antal_termer) = *t;//This is were the program crashes
antal_termer++;
This crashes because you probably haven't allocated enough memory. Your best choice is to use a std::vector instead of a dynamic array.
Is term allocated term = new Term; or term = new Term[sz];?
If it's the first, you can only store one object, and term+antal_termer goes beyond that. If it's the second, you run into problems if antal_termer >= sz.
The std::vector option gives you automatic management:
std::vector<Term> terms;
Term potens; //why use new?
terms.push_back(potens);
Note that I'm using objects, not pointers. For pointers, it'd be
std::vector<Term*> terms;
Term* potens = new Term;
terms.push_back(potens);
But note that you have to delete the memory when you're done with it.
Pasting in outcome from comments.
antal_termer was not initialised in the constructor, resulting in invalid memory access here:
*(term+antal_termer) = *t;
As the code is copying t, via assignment, you can delete potens; after the call to addTerm(). The code must prevent going beyond the end of the term array in addTerm(), otherwise another invalid memory access will occur:
void Polynom::addTerm(Term *t){
if (antal_termer < 10) // Use constant instead of literal 10
{
*(term+antal_termer) = *t;
antal_termer++;
}
}
I have a structure Defined in the Header file for a class i am working in, and i am trying to use the Struct in one of the methods of the class. It looks basically like this:
struct example
{
double a;
int b;
...
};
in the header above my class definition, and then in the cpp file, i have:
void exampleclass::test(){
struct example *teststruct;
teststruct->a = 0; //This line causes a access violation
}
why do i get an error here? Im sure im doing something clompletly wrong here, and i must say im a huge structure rookie.
What about allocating the memory for your structure ?
something like :
example* teststruct = new example;
teststruct->a = 0;
struct example *teststruct; is a pointer to an instance of the struct example. (By the way, C++ does not require the struct prefix, leave it off.)
So, what example are you pointing at? (Hint: none, you haven't initialized the variable.) You could dynamically allocate one: example *teststruct = new example();, and later delete it: delete teststruct;.*
Of course, you should prefer automatic (stack) allocation over dynamic allocation, and just do:
example teststruct;
teststruct.a = 0;
*And you should never actually handle raw allocations like this. Put them in a smart pointer. At the very least, std::auto_ptr.
As you've written it teststruct points to some random location in memory so accessing it, by doing teststruct->a = 0; takes you into undefined behavior land. So you can have - if you're really lucky - an instant error [like access violation, bus error, segmentation fault etc] or it will run without problems.
You need to either allocate memory for teststruct like Max said or create it on the stack and do something like:
struct example teststruct;
teststruct.a = 0; //This line does not cause an access violation
(Disclaimer: I have removed the Qt tag in case the problem is in my syntax / understanding of the references involved here)
I have a foreach loop with an object Member. When I enumerate through the list and try to access a member field, the debugger stops and I get a message:
Stopped: 'signal-received' -
The assert failure is:
inline QString::QString(const QString &other) : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }
I have checked if the member is NULL, and it isn't. I have tried re-working the code, but I keep failing on this simple call.
Some thing's I missed out. MemberList is a singleton (definitely initialized and returns a valid pointer) that is created as the application launches and populates the MemberList with Members from a file. When this is created, there are definitely values, as I print them to qDebug(). This page is literally the next page. I am unsure as to how the List items can be destroyed.
The code is as follows:
int i = 0;
QList<Member*> members = ml->getMembers();
foreach (Member* mem, members)
{
QString memID = mem->getMemberID(); // Crash happens here
QListWidgetItem *lstItem = new QListWidgetItem(memID, lsvMembers);
lsvMembers->insertItem(i, lstItem);
i++;
}
The Member classes get is as follows:
QString getMemberID() const;
and the actual function is:
QString Member::getMemberID() const
{
return MemberID;
}
The ml variable is received as follows:
QList<Member*> MemberList::getMembers()
{
return MemberList::getInstance()->memberList;
}
Where memberList is a private variable.
Final answer:
I decided to rework the singleton completely and found that I was not instantiating a new Member, rather reusing the previous object over and over. This caused the double reference. S'pose thats pointers for you. Special thanks to Troubadour for the effort!
If mem is not null it could still be the case that the pointer is dangling i.e. the Member it was pointing to has been deleted.
If Member inherits from QObject then you could temporarily change your QList<Member*> that is stored in ml (assuming that's what's stored in ml) into a QList< QPointer<Member> >. If you then get a null QPointer in the list after calling getMembers or at any point during the loop then the object must have been destroyed at some point.
Edit
As regards the singleton, are you sure it's initiliased properly? In other words does MemberList::getInstance() return a valid pointer or just a random uninitialised one?
Edit2
Since we've exhausted most possibilities I guess it must be in the singleton somewhere. All I can suggest is to keep querying the first item in the list to find out exactly where it goes bad.