I am trying to play with __attribute__
to allow a function to be essentially compiled with different flags from the rest of the code. For example:
#include <iostream>
#include <vector>
void MyNormalFunction();
void MyDebugabbleFunction() __attribute__((optimize(0)));
void MyNormalFunction()
{
std::cout << "Test" << std::endl;
std::vector<int> a;
for(unsigned int i = 0; i < 10; ++i)
{
a.push_back(i);
}
}
void MyDebugabbleFunction()
{
std::cout << "Test" << std::endl;
std::vector<int> a;
for(unsigned int i = 0; i < 10; ++i)
{
a.push_back(i);
}
}
int main()
{
MyNormalFunction();
MyDebugabbleFunction();
return 0;
}
I am building with -g -O2, but I want to be able to sanely debug MyDebugabbleFunction()
— so I used the __attribute__((optimize(0)))
on its declaration. However, I can't really tell any difference when stepping through these two functions with a debugger. I would expect the "seemingly erratic" behavior that I usually see when trying to step through optimized code in MyNormalFunction
, but the standard "-g"-only debugger behavior in MyDebuggableFunction
.
Is it that I have done something wrong with __attribute__
? Or that I have used bad demo code (i.e. code that doesn't get "optimized a lot") inside the two functions? Or am I misinterpreting what the difference is supposed to be in the debugger?
I am using gcc 4.6.
EDIT based on GManNickG's suggestion
I used this code instead, and built with -O2 -g:
#include <iostream>
#include <vector>
int MyNormalFunction();
int MyDebugabbleFunction() __attribute__((optimize(0)));
int MyNormalFunction()
{
int val = 0; // breakpoint here - debugger does NOT stop here
val = 1;
val = 2;
return val;
} // debugger stops here instead
int MyDebugabbleFunction()
{
int val = 0; // breakpoint here - debugger stops here and steps through the next 3 lines as if it were built with only -g
val = 1;
val = 2;
return val;
}
int main()
{
int a = MyNormalFunction();
std::cout << a << std::endl;
int b = MyDebugabbleFunction();
std::cout << b << std::endl;
return 0;
}
Try a test like this instead:
int MyNormalFunction()
{
int val = 0;
val = 1;
val = 2;
// should optimize to return 2
return val;
}
int MyDebuggableFunction() __attribute__((optimize(0)));
{
int val = 0;
val = 1;
val = 2;
// could optimize to return 2, but attribute blocks that
return val;
}
int main()
{
// we need to actually output the return values,
// or main itself could be optimized to nothing
std::cout << MyNormalFunction() << std::endl;
std::cout << MyDebuggableFunction() << std::endl;
}
It'll make it much easier to follow.
Note that you should start in main
, when stepping through, because it most likely will be reduced to:
int main()
{
std::cout << 2 << std::endl;
std::cout << MyDebuggableFunction() << std::endl;
}
If you're up for it, looking at the disassembly makes this task much easier.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With