GDB сообщает неверный адрес для параметра в конструкторе объекта c ++ - PullRequest
6 голосов
/ 24 января 2012

Я испытываю странное поведение, когда 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, struct, указатель, но я не могу воспроизвести странность.
Также я попытался установить формат отладки на -ggdb.

Вопросы:

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

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

1 Ответ

0 голосов
/ 06 апреля 2015

Из любого поста (https://gcc.gnu.org/ml/gcc/2001-04/msg01037.html) кажется, что -gstabs или -gstabs + - правильные флаги при отладке C ++. Надеюсь, это может помочь.

...