Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

G++ and __attribute__((optimize)) not changing debugger behavior

Tags:

c++

gcc

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;
}
like image 534
David Doria Avatar asked Nov 04 '22 17:11

David Doria


1 Answers

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.

like image 174
GManNickG Avatar answered Nov 12 '22 12:11

GManNickG