GDB сообщает неверный адрес для параметра в конструкторе объекта c ++

Я испытываю странное поведение, когда GDB передает строку в качестве параметра конструктору. Код работает нормально, но когда я перехожу в отладчик, GDB, кажется, думает, что мой параметр находится по другому адресу, чем он есть.Кто-нибудь знает, что здесь происходит?

Вот простейшая программа, которую я могу создать, которая демонстрирует проблему:

--(jwcacces@neptune)--------------------------------------------(/home/jwcacces)--
--$ nl gdb_weird.cpp
     1  #include <iostream>
     2  #include <string>
     3
     4  class C
     5  {
     6  public:
     7     C(std::string str)
     8     {
     9        std::string* str_ptr = &str;
    10        std::cout << "Address of str: " << &str << std::endl;
    11        std::cout << "Address in str_ptr: " << str_ptr << std::endl;
    12        std::cout << "Value of str: " << str << std::endl;
    13     };
    14  };
    15
    16  int main(int, char*[])
    17  {
    18     std::string s("Hello, World!");
    19     C c(s);
    20     return 0;
    21  }

Компиляция с отладочной информацией, без оптимизации.
Обратите внимание, что я вижу эту проблему при компиляции для x86, x64 и mingw (x86).
На других архитектурах не пробовал.

--(jwcacces@neptune)--------------------------------------------(/home/jwcacces)--
--$ g++ -O0 -g -Wall -Wextra gdb_weird.cpp -m32

--(jwcacces@neptune)--------------------------------------------(/home/jwcacces)--
--$ g++ --version
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Теперь, отладка:

--(jwcacces@neptune)--------------------------------------------(/home/jwcacces)--
--$ gdb a.out
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/jwcacces/a.out...done.

(gdb) br main
Breakpoint 1 at 0x80488ce: file gdb_weird.cpp, line 18.

(gdb) run
Starting program: /home/jwcacces/a.out

Breakpoint 1, main () at gdb_weird.cpp:18
18         std::string s("Hello, World!");

(gdb) next
19         C c(s);

(gdb) step
C::C (this=0xffffd74f, str=...) at gdb_weird.cpp:9
9             std::string* str_ptr = &str;

Вот странность: когда я пытаюсь вывести str , я получаю мусор:

(gdb) output str
{
  static npos = <optimized out>,
  _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>},
                                           <No data fields>},
                 _M_p = 0xffffd748 "\024\260\004\b\364\177\354\367\360\211\004\b\364\177\354", <incomplete sequence \367>
                }
}

Итак, что GDB считает адресом str есть?

(gdb) output &str
(std::string *) 0xffffd734

И что программа считает адресом str ?

(gdb) next
10            std::cout << "Address of str: " << &str << std::endl;

(gdb) next
Address of str: 0xffffd748
11            std::cout << "Address in str_ptr: " << str_ptr << std::endl;

(gdb) next
Address in str_ptr: 0xffffd748
12            std::cout << "Value of str: " << str << std::endl;

Это действительно странно, программа считает, что str находится по адресу 0xffffd748 , но GDB считает, что его адрес 0xffffd734
И когда вы выводите строковый объект, который будет находиться в 0xffffd748 , он работает правильно.

(gdb) output *(std::string*)0xffffd748
{
  static npos = <optimized out>,
  _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, 
                                           <No data fields>
                                          },
                 _M_p = 0x804b014 "Hello, World!"
                }
}

И сама программа не имеет проблем с использованием параметра:

(gdb) next
Value of str: Hello, World!
13         };

(gdb) continue
Continuing.
[Inferior 1 (process 19463) exited normally]

(gdb) quit

Я пробовал изменить тип параметра конструктора на int, структуру, указатель, но я не могу воспроизвести странность.
Кроме того, я попытался установить формат отладки на -ggdb.

Вопросы:

  • Что здесь происходит?
  • Почему gdb говорит, что член npos std :: string оптимизирован (возможно, оптимизирован вне библиотеки) ), и имеет ли это какое-либо отношение к этому?
  • Это просто совпадение, что в "объекте", где, по мнению GDB, находится str , член _M_p указывает на 0xffffd748 , адрес, по которому на самом деле находится str ?
  • При каких еще обстоятельствах происходит такое поведение?

---- WOAH, Прорыв --- -
Если я установил формат отладки на -gstabs +, GDB правильно получит адрес str .
Означает ли это, что формат отладки gdb работает некорректно?

7
задан James Caccese 24 January 2012 в 00:26
поделиться