Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

How feasible would it be for something like gdb to be able to use a C++ interpreter (whether icpp, or even a souped up `constexpr` interpreter from the compiler) to help with "optimized out" functions?

gdb also doesn't handle overloaded functions well, e.g. `x[i]`.



GDB does have hooks for interpreters to be executed within it, but I haven't managed to make this work. https://sourceware.org/gdb/current/onlinedocs/gdb.html/JIT-I....


It does though? Just compiled a small program that creates a vector, and GDB is perfectly happy accessing it using this syntax. It will even print std::string’s correctly if you cast them to const char* by hand. (Linux x86-64, GDB 14.2.)


I've defined a few pretty printers, but `operator[]` doesn't work for my user-defined types. Knowing it works for vectors, I'll try and experiment to see if there's something that'll make it work.

  (gdb) p unrolls_[0]
  Could not find operator[].
  (gdb) p unrolls_[(long)0]
  Could not find operator[].
  (gdb) p unrolls_.data_.mem[0]
  $2 = {
`unrolls_[i]` works within C++. This `operator[]` method isn't even templated (although the container type is); the index is hard-coded to be of type `ptrdiff_t`, which is `long` on my platform.

I'm on Linux, gdb 15.1.


> This `operator[]` method isn't even templated (although the container type is)

That might be it. If that operator isn’t actually ever emitted out of line, then GDB will (naturally) have nothing to call. If it helps, with the following program

  template<typename T>
  struct Foo {
      int operator[](long i) { return i * 3; }
  };
  
  Foo<bool> bar;
  template int Foo<bool>::operator[](long); // [*]
  
  int main(void) {
      Foo<int> foo;
      __asm__("int3");
      return foo[19];
  }
compiled at -g -O0 I can both `p foo[19]` and `p bar[19]`, but if I comment out the explicit instantiation marked [*], the latter no longer works. At -g -O2, the former does not work because `foo` no longer actually exists, but the latter does, provided the instantiation is left in.


Can confirm, this works for me in my actual examples, thanks!


> It will even print std::string’s correctly if you cast them to const char* by hand

What does that mean? I think `print str.c_str()` has worked for me in GDB before, but sounds like you did something different.


I was observing that `p (const char *)str` also worked in my experiment, but I’m far from a C++ expert and upon double-checking this seems to have been more of an accident than intended behaviour, because there is no operator const_pointer in basic_string that I can find. Definitely use `p str.c_str()`.


If your std::string was using a short string optimization, that would explain the “accident”.

Some implementations even put char[0] at the first byte in the optimized form.


That explanation doesn't work IMO, unless `str` is a std::string pointer, which is contrary to the syntax GP suggested with `str.c_str()`.

It doesn't seem possible in actual C++ that the cast from non-pointer to pointer would work at all (even if a small string happens to be inlined at offset 0.) Like GP, I looked for a conversion operator, and I don't think it's there. Maybe it is a feature of the gdb parser.


Good point, but if it’s a long string, 2/3 of the most common implementations would make the first word the c_str()-equivalent pointer:

https://devblogs.microsoft.com/oldnewthing/20240510-00/?p=10...


So it's actually printing *(const char **)&s?


The first pointer-sized chunk of the string structure is a pointer to the C-string representation. So the cast works as written.


Well, no, because (const char *)str is nonsense, if str is an std::string.


Not to the debugger. If the first 8 bytes of the object referenced by str is a char* the debugger is perfectly capable of using it that way.


this "optimized out" thing is bullshit as hell




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: