I have the following method in a template class (a simple FIFO queue) and while GDB debugging, I found that the statement to reassign the pointer 'previous' to 'current' seems to do nothing.
previous starts as NULL and current is not NULL when this statement is executed, yet previous remains as NULL.
Has anyone seen anything like this before?
inline int search(QueueEntry<T> *current,QueueEntry<T> *previous, unsigned long long t)
{
while(current && !(current->getItem()->equals(t)))
{
previous = current; //**this line doesn't seem to work**
current = current->getNext();
}
if(current)
return 1;
return 0;
}
The assignment is optimized away by the compiler because it doesn't have any effect on the function's behavior. You reassign previous every time through the loop, but do nothing else with it.
The bug, if any, is in the rest of the function.
Where are you inspecting the value of previous? If you're doing it within this function, after the assignment, then make sure the build has optimizations turned off, and then try it again.
On the other hand, if you're watching previous outside the scope of this function, then it'll never get modified. When you call search() a copy of pointer previous gets loaded onto the stack and you're modifying this copy. The modification disappears after the function exits. To keep the modification around do something like this:
inline int search(QueueEntry<T> *current,QueueEntry<T> **previous, unsigned long long t)
{
...
*previous = current;
...
}
The call to search() will have to pass the address to the pointer now instead of the value.
Or, you can pass a reference and the rest of your code remains the same.
inline int search(QueueEntry<T> *current,QueueEntry<T> *&previous, unsigned long long t)
You never use your previous variable, therefore, especially if you're compiling with gcc -O2, it's considered a loop invariant, and is optimized away.
Try turning all your optimizations off.
It is likely that the compiler is noticing that that previous=current isn't necessary to do and is simply compiling it out
Related
I'm making a C++ assignment for school and I've run into a peculiar problem. It's most likely memory corruption or whatever but as I am really mediocre at C++ I don't know how to solve it.
void Inventory::addItem(Item *item, const int stackCount) {
//find the item
Item *fi = findItem(item->id);
if(fi == nullptr)
{
Item *newItem = (Item *)malloc(sizeof(Item));
//std::cout << stackCount << std::endl;
memcpy(&newItem, &item, sizeof(Item));
newItem->stack = stackCount;
current.push_back(newItem);
}
}
I've got this piece of code, where it copies the Item's properties to another item. This works fine, and it carries everything over. Except something weird goes on with the stackCount variable.
There's a commented cout, and with it commented out the stackCount value is wrong. It will be at around 32k or so.
If it's not commented out, the value will be correct! Which is 1! (I am testing this in another function)
When placed behind the memcpy statement, the value is always wrong. Which of course leads me to believe that it's indeed memory corruption.
So I'm really quite confused. What exactly is c++ doing here?
memcpy(&newItem, &item, sizeof(Item));
What you're saying here is to copy from the address of item, aka a pointer to a pointer to an Item, to the address of newItem, aka another pointer to a pointer to an Item.
Since both of these are stack variables, and I'm guessing that sizeof(Item) != sizeof(Item**), you're invoking undefined behaviour here.
The reason the StackSize variable is only working when printing it is pure luck on your part; the compiler is most likeley just moving some variables around on the stack to try to optimize stack/register use, and moving the variable out of the area to be overwritten in the process.
Since you're using C++, you shouldn't be using memcpy in the first place. Write a copy constructor and an operator= instead to copy Item values.
Memcpy should get an address of destination and source.
You are passing "address to address".
Change:
memcpy(&newItem, &item, sizeof(Item));
to
memcpy(newItem, item, sizeof(Item));
Also, as stated by #Bathsheba and #Some-programmer-dude and #yksisarvinen, you shouldn't use malloc. Consider creating a copy constructor and/or assignment operator.
I have the following function:
std::vector<std::vector<Surfel>> testAddingSift(
const Groundtruth &groundtruth,
SurfelHelper &surfelHelper) {
for (int k = 0; k < 10; k++) {
std::cout << "hej" << k <<std::endl;
}
}
When I forgot to return a vector<vector<Surfel>> I got an infinite loop:
hej1025849
hej1025850
hej1025851
hej1025852
When I return a vector<vector<Surfel>> I get:
hej0
hej1
hej2
hej3
hej4
hej5
hej6
hej7
hej8
hej9
Of course it was a mistake to forget to return the vector, but why is the for-loop affected?
I am using a MacBook Pro with Sierra and CLion and I think it is clang.
Failure to return from a function with non-void return type is undefined behavior. Doing so makes it, by definition, nearly impossible to reason about the resulting behavior. This can affect the behavior of code that comes before the point where undefined behavior would be expected to be encountered.
The proper answer here is that this is, of course, undefined behavior, so anything could happen. A more interesting question is, how in the world would something silly, like forgetting a return statement, lead to an infinite loop?
It is not the first time I forget to return something, but that has never caused this kind of problems before.
My best guess is that the result that you see has to do with returning an object by value when the object has a non-trivial copy constructor. In your case, copy constructor is rather non-trivial, because it needs to deal with nested arrays. In particular, I suspect that the infinite loop would go away if you change return type to an int (the behavior would remain undefined, though).
My guess is that when your loop calls operator << it places return address on the stack. Once operator << returns, the stack frame becomes unused, but its content remains intact. I suspect that the code for copying the returned vector re-interprets the content of the "garbage" stack frame as a vector with lots of elements, and invokes loop's body instead of copying array elements.
This is just one possibility. If you would like to find out what is happening, the proper way would be to dig through the disassembly.
First of all: I know that most optimization bugs are due to programming errors or relying on facts which may change depending on optimization settings (floating point values, multithreading issues, ...).
However I experienced a very hard to find bug and am somewhat unsure if there is any way to prevent these kind of errors from happening without turning the optimization off. Am I missing something? Could this really be an optimizer bug? Here's a simplified example:
struct Data {
int a;
int b;
double c;
};
struct Test {
void optimizeMe();
Data m_data;
};
void Test::optimizeMe() {
Data * pData; // Note that this pointer is not initialized!
bool first = true;
for (int i = 0; i < 3; ++i) {
if (first) {
first = false;
pData = &m_data;
pData->a = i * 10;
pData->b = i * pData->a;
pData->c = pData->b / 2;
} else {
pData->a = ++i;
} // end if
} // end for
};
int main(int argc, char *argv[]) {
Test test;
test.optimizeMe();
return 0;
}
The real program of course has a lot more to do than this. But it all boils down to the fact that instead of accessing m_data directly, a (previously unitialized) pointer is being used. As soon as I add enough statements to the if (first)-part, the optimizer seems to change the code to something along these lines:
if (first) {
first = false;
// pData-assignment has been removed!
m_data.a = i * 10;
m_data.b = i * m_data.a;
m_data.c = m_data.b / m_data.a;
} else {
pData->a = ++i; // This will crash - pData is not set yet.
} // end if
As you can see, it replaces the unnecessary pointer dereference with a direct write to the member struct. However it does not do this in the else-branch. It also removes the pData-assignment. Since the pointer is now still unitialized, the program will crash in the else-branch.
Of course there are various things which could be improved here, so you might blame it on the programmer:
Forget about the pointer and do what the optimizer does - use m_data directly.
Initialize pData to nullptr - that way the optimizer knows that the else-branch will fail if the pointer is never assigned. At least it seems to solve the problem in my test-environment.
Move the pointer assignment in front of the loop (effectively initializing pData with &m_data, which then could also be a reference instead of a pointer (for good measure). This makes sense because pData is needed in all cases so there is no reason to do this inside the loop.
The code is obviously smelly, to say the least, and I'm not trying to "blame" the optimizer for doing this. But I'm asking: What am I doing wrong? The program might be ugly, but it's valid code...
I should add that I'm using VS2012 with C++/CLI and v110_xp-Toolset. Optimization is set to /O2. Please also note that if you really want to reproduce the problem (that's not really the point of this question though) you need to play around with the complexity of the program. This is a very simplified example and the optimizer sometimes doesn't remove the pointer assignment. Hiding &m_data behind a function seems to "help".
EDIT:
Q: How do I know that the compiler is optimizing it to something like the example provided?
A: I'm not very good at reading assembler, I have looked at it however and have made 3 observations which make me believe that it's behaving this way:
As soon as optimization kicks in (adding more assignments usually does the trick) the pointer assignment has no associated assembler statement. It also hasn't been moved up to the declaration, so it's really left uninitialized it seems (at least to me).
In cases where the program crashes, the debugger skips the assignment statement. In cases where the program runs without problems, the debugger stops there.
If I watch the content of pData and the content of m_data while debugging, it clearly shows that all assignments in the if-branch have an effect on m_data and m_data receives the correct values. The pointer itself it still pointing to the same uninitialized value it had from the beginning. Therefore I have to assume that it is in fact not using the pointer to make the assignments at all.
Q: Does it have to do anything with i (Loop unrolling)?
A: No, the actual program actually uses do { ... } while() to loop over a SQL SELECT-resultset so the iteration count is completely runtime-specific and cannot be predetermined by the compiler.
It sure looks like an bug to me. It's fine for the optimizer to eliminate the unnecessary redirection, but it should not eliminate the assignment to pData.
Of course, you can work around the problem by assigning to pData before the loop (at least in this simple example). I gather that the problem in your actual code isn't as easily resolved.
I also vote for an optimizer bug if it is really reproducible in this example. To overrule the optimizer you could try to declare pData as volatile.
I have a C++ class; this class is as follows:
First, the header:
class PageTableEntry {
public:
PageTableEntry(bool modified = true);
virtual ~PageTableEntry();
bool modified();
void setModified(bool modified);
private:
PageTableEntry(PageTableEntry &existing);
PageTableEntry &operator=(PageTableEntry &rhs);
bool _modified;
};
And the .cpp file
#include "PageTableEntry.h"
PageTableEntry::PageTableEntry(bool modified) {
_modified = modified;
}
PageTableEntry::~PageTableEntry() {}
bool PageTableEntry::modified() {
return _modified;
}
void PageTableEntry::setModified(bool modified) {
_modified = modified;
}
I set a breakpoint on all 3 lines in the .cpp file involving _modified so I can see exactly where they are being set/changed/read. The sequence goes as follows:
Breakpoint in constructor is triggered. _modified variable is confirmed to be set to true
Breakpoint in accessor is triggered. _modified variable is FALSE!
This occurs with every instance of PageTableEntry. The class itself is not changing the variable - something else is. Unfortunately, I don't know what. The class is created dynamically using new and is passed around (as pointers) to various STL structures, including a vector and a map. The mutator is never called by my own code (I haven't gotten to that point yet) and the STL structures shouldn't be able to, and since the breakpoint is never called on the mutator I can only assume that they aren't.
Clearly there's some "gotcha" where private variables can, under certain circumstances, be changed without going through the class's mutator, triggered by who-knows-what situation, but I can't imagine what it could be. Any thoughts?
UPDATE:
The value of this at each stage:
Constructor 1: 0x100100210
Constructor 2: 0x100100400
Accessor 1: 0x1001003f0
Accessor 2: 0x100100440
UPDATE2:
(code showing where PageTableEntry is accessed)
// In constructor:
_tableEntries = std::map<unsigned int, PageTableEntry *>();
// To get an entry in the table (body of testAddr() function, address is an unsigned int:
std::map<unsigned int, PageTableEntry *>::iterator it;
it = _tableEntries.find(address);
if (it == _tableEntries.end()) {
return NULL;
}
return (PageTableEntry *)&(*it);
// To create a new entry:
PageTableEntry *entry = testAddr(address);
if (!entry) {
entry = new PageTableEntry(_currentProcessID, 0, true, kStorageTypeDoesNotExist);
_tableEntries.insert(std::pair<unsigned int, PageTableEntry *>(address, entry));
}
Those are the only points at which PageTableEntry objects are stored and retrieved from STL structures in order to cause the issue. All other functions utilize the testAddr() function to retrieve entries.
UNRELATED: Since C++ now has 65663 questions, and so far 164 have been asked today, that means that only just today the number of C++ tagged questions exceeded a 16-bit unsigned integer. Useful? No. Interesting? Yes. :)
Either your debugger isn't reporting the value correctly (not unheard of, and even expected in optimized builds) or you have memory corruption elsewhere in your program. The code you've shown is more-or-less fine and should behave as you expect.
EDIT corresponding to your 'UPDATE2':
The problem is in this line:
return (PageTableEntry *)&(*it);
The type of *it is std::pair<unsigned const, PageTableEntry*>&, so you're effectively reinterpret-casting a std::pair<unsigned const, PageTableEntry*>* to a PageTableEntry*. Change that line to:
return it->second;
Keep an eye out for other casts in your codebase. Needing a cast in the first place is a code smell, and the result of doing a cast incorrectly can be undefined behavior, including manifesting as memory corruption as you're seeing here. Using C++-style casts instead of C-style casts makes it trivial to find where casts occur in your codebase so they can be reviewed easily (hint, hint).
std::map<>::find() returns an iterator which when dereferenced returns a std::map<>::value_type. The value_type in this case is a std::pair<>. You're returning the address of that pair rather than the PageTableEntry. I believe you want the following:
// To get an entry in the table (body of testAddr() function, address is an unsigned int:
std::map<unsigned int, PageTableEntry *>::iterator it;
it = _tableEntries.find(address);
if (it == _tableEntries.end()) {
return NULL;
}
return (*it).second;
P.S.: C-style casts are evil. The compiler would have issued a diagnostic with a C++ cast in place. :)
Try looking at the value of this at each breakpoint.
That copy constructor and assignment operator are both going to be used a lot if you're using STL containers. Maybe if you show us the code for those, we would see something wrong.
Could you add another unique value to the class to track the PageTableEntry s?
I know that I've had problems like this where the real problem was that there were multiple entries that looked the same and the breakpoints might switch PageTableEntry s without me realizing it.
CARD& STACK::peek()
{
if(cards.size == 0)
{
CARD temp = CARD {-1, -1};
return temp;
}
return cards.back();
}
This is the function I am having trouble with.
CARD is just a struct with two int variables, called rank and suit.
STACK is a class that manages an std::vector<CARD>, that is called cards.
The function is supposed to return a reference to the card on top of the stack, or return the reference to a dummy card if the vector is empty.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do I do about it?
Second, I am trying to use this function with another function I created called cardToString
char* cardToString(CARD& c);
It is supposed to use the rank and suit variables in the passed CARD to look up string values in a table, concatenate the two strings together, and return a pointer to the new string.
So the end result looks like:
cout<<cardToString(deck.peek())<<"\n";
but this line of code will execute up to the cardToString function, then just stop for some reason. It is annoying the hell out of me because it just stops, there is no error message and there does not look like there is anything wrong to me.
Can somebody help me out?
Edit: here is the cardToString function
char *cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
{
std::cout<<"returned null";
return NULL;
}
char *buffer = new char[32];
strcpy(buffer, RANKS[c.r]);
strcat(buffer, " of ");
return strcat(buffer, SUITS[c.s]);
}
I specifically want the function STACK.peek() to return the address of the CARD that already exists on the top of the STACK. It seems to make more sense to do that than to create a copy of the card that I want to return.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do i do about it?
A local variable, as it name implies, is local to the function it belongs to, so it's destroyed as the function returns; if you try to return a reference to it, you'll return a reference to something that will cease to exist at the very moment the function returns.
Although in some cases this may seem to work anyway, you're just being lucky because the stack hasn't been overwritten, just call some other function and you'll notice it will stop working.
You have two choices: first of all, you can return the CARD by value instead of reference; this, however, has the drawback of not allowing the caller to use the reference to modify the CARD as is stored in the vector (this may or may not be desirable).
Another approach is to have a static dummy CARD instance stored in the STACK class, that won't have these lifetime problems, and that can be returned when you don't have elements in the vector; however, you should find a method to "protect" its field, otherwise a "stupid" caller may change the values of your "singleton" dummy element, screwing up the logic of the class. A possibility is to change CARD in a class that will encapsulate its fields, and will deny write access to them if it's the dummy element.
As for the cardToString function, you're probably doing something wrong with the strings (and I'm almost sure you're trying to return a local also in this case), but without seeing the body of the function it's difficult to tell what.
By the way, to avoid many problems with strings I suggest you to use, instead of char *, the std::string class, which takes away most of the ugliness and of the low level memory management of the usual char *.
Also, I'd suggest you to change cardToString to take a const reference, because most probably it doesn't need to change the object passed as reference, and it's good practice to clearly mark this fact (the compiler will warn you if you try to change such reference).
Edit
The cardToString function should be working fine, as long as the RANKS and SUITS arrays are ok. But, if you used that function like you wrote, you're leaking memory, since for each call to cardToString you make an allocation with new that is never freed with delete; thus, you are losing 32 bytes of memory per call.
As stated before, my tip is to just use std::string and forget about these problems; your function becomes as simple as this:
std::string cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
return "(invalid card)";
return std::string(RANKS[c.r]) + " of " + SUITS[c.s];
}
And you don't need to worry about memory leaks and memory allocations anymore.
For the reference/value thing: if the caller do not need to use the reference to modify the object stored in the vector, I strongly suggest passing it by value. The performance hit is negligible: two ints instead of one pointer means 8 vs 4 bytes on most 32 bit architectures, and 8 bytes vs 8 bytes on most 64 bit machines (and also accessing the fields via pointer has a small cost).
This kind of micro-optimization should be the last of your concerns. Your top priority is to write correct and working code, and the last thing you should do is to let micro-optimization get in the way of this aim.
Then, if you experience performance problems, you'll profile your application to find where the bottlenecks are and optimize those critical points.
You cannot return a reference to a local variable, because the local variable no longer exists when the function returns.
You need to return by-value, not by-reference (i.e. CARD STACK::peek() { ... }).