Here is a quick snippet of my code to parse PDB files for molecular dynamics simulations:
Structure *s = new Structure(pdb_filename);
Chain *c = new Chain();
while( ... read file ... ) {
if ( ... new chain ... ) {
Chain *c = new Chain();
s->add_child(c); // Add reference to a vector to
// save the Chain for later
}
}
When the containing function is called, the code acts as normal and gives brand new Structure and Chain objects as in the first two lines of the snippet.
When the criteria for a new chain is met again while looping over the file, the code returns the same Chain pointer to the object as before.
Will g++ give the same pointer over and over? Is there any way to get around this?
If I add the c pointer to the 's' children vector, I assume calling delete c will cause even larger headaches?
Structure *s = new Structure(pdb_filename);
Chain *c = new Chain();
You just defined c here
while( ... read file ... ) {
if ( ... new chain ... ) {
Chain *c = new Chain();
You just defined c here again shadowing the other one.
When the criteria for a new chain is met again while looping over the
file, the code returns the same Chain pointer to the object as before.
Now which one of the two you're looking at?
I think you can see the problem already.
the code returns the same Chain pointer to the object as before
That is hard to believe.
Will g++ give the same pointer over and over?
No. Each time you call new Chain it's a different Chain. It's a different pointer, pointing to different memory (that's why it's new). It's also shadowing the c before the while.
new Chain() should give a different pointer each time
I think I may have an inkling what your problem is--
The c within your loop does not refer to the same variable as the c outside your loop. The c outside your loop will retain its same value all the way through.
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'm working on using pointers to add objects to a queue and ran into a weird behavioral problem I can't quite figure out.
Each object that gets added to the queue has a 'next' pointer that links them all together and I have a 'start' and 'end' pointer to keep track where each end of the queue is.
The problem I have is that when I pass the end pointer and the object (which is stored in pArray by its processID), it also changes the start pointer -- even though I'm not passing it to the function.
// snippet from my main.cpp
RQCount = 0;
if (RQCount == 0)
{
RQStart = &pArray[processID];
RQStart -> next = &pArray[processID];
endRQ = &pArray[processID];
pArray[processID].setStatus("Ready");
CPUHolder = RQStart;
CPU = RQStart -> CPUBurst;
RQStart ->pStatus = "Executing";
}
else
{
*endRQ = FCFS(endRQ, &pArray[processID]);
pArray[processID].setStatus("Ready")
}
RQCount++;
FCSC Method:
PCB FCFS (PCB *endRQ, PCB *obj)
{
endRQ -> next = obj;
endRQ = obj;
return *endRQ;
};
I've narrowed it down to the function, and what really stumps me is that I move those two lines of code to my main, it runs and behaves just fine. It's when I add the function it doesn't. I think it has to do with how I'm dealing with the pointers and dereferencing, but I could use some help understanding this. Thanks!
EDIT:
To emphasize, I'm not having an issue with variables not changing in the function, as someone marked this a duplicate question for. The issue is after the function is called, it changes RQStart (which is not passed to the function).
If I don't use a function, RQStart stay the same, when I use the function, RQStart changes to a different object.
If you do
RQStart = &pArray[processID];
// ...
endRQ = &pArray[processID];
and then pass endRQ to the function, that will be the same as if you passed RQStart.
So when you change endRQ->next that will also change RQStart->next.
This is one reason for the standard containers to have end() point one past the last element, and not to the last element.
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 am writing an application using the crypto++ library. For those not familiar with it, the ECB_Mode template classes inherit from CipherModeBase. The program compiles and runs, but the output I am getting is incorrect. When I call the encryption method from the cipher_object, it doesn't work the same way as if I use an ECB_Mode object directly. I have verified that the options object instance variables are getting assigned correctly. I would like to create the instances within an if_then_else structure or switch_case so I can keep the code nice and DRY. What am I doing wrong?
Here is what I am trying but doesn't work:
CipherModeBase *cipher_object;
cipher_object == NULL;
if(options->cipher == BS_AES)
{
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
else if(options->cipher == BS_TWOFISH)
{
ECB_Mode<Twofish >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
cipher_object->processData(args);
Here is what does work:
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
ecbEncryption.processData(args);
PS. I know not to use ECB mode. I just don't want to mess with IVs until I can get everything working. I am also relatively inexperienced with C++.
Your ecbEncryption objects are declared on the stack within the if and else scopes. (Scopes are the things enclosed by curly brackets).
An object will be destroyed when the scope it was declared in exits. So, the object you're calling processData on has been deleted before you call that method. Clearly that won't work.
One option is you could declare the objects on the heap instead of the stack. That way the lifetime could be controlled to work the way you want.
Try to use a std::unique_ptr for the cipher_object instead of a raw pointer. Then, in the if and else clauses assign to it like:
cipher_object.reset( new ECB_Mode<AES>::Encryption(options->key, options->keylen) );
Then the object will remain on the heap until the end of the cipher_object's scope, at which point the unique_ptr will delete it for you. And, the cipher_object's scope will last until after you call any methods on it.
Here:
cipher_object == NULL;
if(options->cipher == BS_AES)
{
// v
ECB_Mode<AES >::Encryption ecbEncryption(options->key, options->keylen);
cipher_object = &ecbEncryption;
}
ecbEncryption is local to that scope. You are storing the address of a local, and using it after it goes out of scope. That's undefined behaviour. You should allocate it on the heap using the new keyword:
if(options->cipher == BS_AES)
{
cipher_object = new ECB_Mode<AES >::Encryption(options->key, options->keylen);
}
You should do the same for the other if statement.
Also note that this:
cipher_object == NULL;
Should be changed to this:
cipher_object = NULL;
The problem should be solved using the above code, though.
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++;
}
}