I'm debugging a C++ program in Xcode 5 using lldb, and I would like to evaluate arbitrary expressions in the debugger, particularly those that use overloaded operators.
For example, I created a very simple Xcode 5 C++ project with the following main.cpp and all compiler/linker/etc options set to the default:
#include <iostream>
#include <vector>
int main(int argc, const char * argv[])
{
std::vector<int> vec;
vec.push_back(42);
std::cout << "vec[0] = " << vec[0] << std::endl;
return 0;
}
I set a breakpoint on the return 0; line and ran the program.
Then, at the lldb prompt, printing the vector as a whole works fine:
(lldb) expr vec
(std::__1::vector<int, std::__1::allocator<int> >) $0 = size=1 {
[0] = 42
}
However, I can't access its members using the overloaded operator[]:
(lldb) expr vec[0]
error: call to a function 'std::__1::vector<int, std::__1::allocator<int> >::operator[](unsigned long)' ('_ZNSt3__16vectorIiNS_9allocatorIiEEEixEm') that is not present in the target
error: The expression could not be prepared to run in the target
Similarly, I can't get the iterator (though I have less experience here, so my syntax may be wrong):
(lldb) expr vector<int>::iterator it = vec.begin()
error: use of undeclared identifier 'vector'
error: expected '(' for function-style cast or type construction
error: expected '(' for function-style cast or type construction
error: 3 errors parsing expression
and
(lldb) expr (vector<int>::iterator) vec.begin()
error: use of undeclared identifier 'vector'
error: expected '(' for function-style cast or type construction
error: expected '(' for function-style cast or type construction
error: 3 errors parsing expression
Analogously, printing a simple string works fine:
(lldb) expr string("a")
(std::__1::string) $0 = "a"
However, a simple string concatenation fails:
(lldb) expr string("a") + string("b")
error: invalid operands to binary expression ('string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') and 'string')
error: 1 errors parsing expression
What am I doing wrong? Does lldb support evaluation with overloaded operators?
Thank you in advance!
I just ran into the same issue and apparently found a simple work-around.
You can access i-th element of a vector vec like this:
(lldb) p vec.__begin_[i]
(int) $1 = 100
Note that the C++ standard libraries are set up so that they inline all the templated functions that they can sensibly inline, and no real function copies exist. So for instance, when you go to call std::vector<int>::begin(), there is no such function. All its uses have been inlined.
That is why you are getting errors about "call to function... not present in target." There may be inlined copies of the function, but none we can actually call. As an example, if I build a little C++ program that makes a std::vector, and pushes some elements onto it and then iterates over them, and then do:
(lldb) image lookup -r -n begin
2 matches found in /private/tmp/vector:
Address: vector[0x0000000100000eaf] (vector.__TEXT.__text + 1071)
Summary: vector`main + 1071 [inlined] std::__1::vector<int, std::__1::allocator<int> >::begin() at vector.cpp:12
vector`main + 1071 at vector.cpp:12 Address: vector[0x0000000100000eaf] (vector.__TEXT.__text + 1071)
Summary: vector`main + 1071 [inlined] std::__1::vector<int, std::__1::allocator<int> >::begin() at vector.cpp:12
vector`main + 1071 at vector.cpp:12
So all the instances of the begin & end accessors for std::vector<int> are inlined. And further down in the part that comes from the std c library itself:
12 matches found in /usr/lib/libc++.1.dylib:
Address: libc++.1.dylib[0x000000000003e4ec] (libc++.1.dylib.__TEXT.__text + 252188)
Summary: libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::begin() Address: libc++.1.dylib[0x000000000003e51c] (libc++.1.dylib.__TEXT.__text + 252236)
Summary: libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::begin() const Address: libc++.1.dylib[0x000000000003e574] (libc++.1.dylib.__TEXT.__text + 252324)
and a few more for basic_string, and that's all. So there aren't any real implementations that we can call. Then once we've only got a little bit of the real world of these std objects available to us, the world falls apart in other odd ways as you start to push on it.
lldb isn't currently smart enough to figure out how to reconstitute a templated function/method from the C++ standard library's header files. We don't have enough of the environment in which your code was originally compiled to do that task.
Note that this isn't really a problem with overloaded operators, it is more a problem with the way the std libraries are used by the compiler. Things should work better for your own classes, where at -O0 there isn't so much inlining.
Related
enter image description here
I want to print Buffer member variable in buf_, in other words,
I want to p *(tensorflow::Buffer*)buf_ to print member variables in class Buffer .
Codes in tensorflow, 1.10.1 .
Class relations : class TensorBuffer is base class in tensor.h, Buffer is a template and derived class in tensor.cc
The following is the output of lldb:
frame #0: 0x0000000175abffc0
libtensorflow_framework.so`tensorflow::Tensor::Tensor(this=0x000070000cadd308, a=0x00007fd91ea61500, type=DT_STRING, shape=0x000070000cadd2f0) at tensor.cc:726:3
723 CHECK_NOTNULL(a);
724 if (shape_.num_elements() > 0 || a->ShouldAllocateEmptyTensors()) {
725 CASES(type, buf_ = new Buffer<T>(a, shape.num_elements()));
-> 726 }
(lldb) p buf_
(tensorflow::TensorBuffer *) $17 = 0x00007fd91e927c40
(lldb) p *(Buffer<std::__1::string>*)buf_
error: use of undeclared identifier 'Buffer'
error: expected '(' for function-style cast or type construction
error: expected expression
(lldb) p *(tensorflow::Buffer<std::__1::string>*)buf_
error: no member named 'Buffer' in namespace 'tensorflow'
error: expected '(' for function-style cast or type construction
error: expected expression
line 725 decode :
switch(type)
case DataTypeToEnum<string>::value :
{
typedef string T;
buf_ = new Buffer<T>(a, shape.num_elements(), allocation_attr);
}
Yes, this is a problem with reconstructing template types from the debug info. The DWARF debug info format doesn't have an abstract representation for a template. It only records instantiated templates (i.e. there is no abstract std::vector<T> but only std::vector<int>, vector<std::string>, etc.
Making up a base "std::string" type, for instance, that clang requires for casting, out of a bunch of specific instantiations, is not something lldb has been taught to do yet, and turns out to be fairly tricky.
You can work around this on an ad hoc basis by introducing typedef's for the types you want to print, e.g.:
(lldb) source list -l 1
1 #include <vector>
2 #include <string>
3 #include <stdio.h>
4
5 int
6 main()
7 {
8 using VecType = std::vector<std::string>;
9 std::vector<std::string> my_vec = {"string", "other string"};
10 void *hidden = (void *) &my_vec;
(lldb)
11 VecType *revealed = (VecType *) hidden;
12 return 0;
13 }
14
15
(lldb) expr *(std::vector<std::string> *) hidden
error: no member named 'vector' in namespace 'std'
error: expected '(' for function-style cast or type construction
error: expected expression
(lldb) expr *(VecType *) hidden
(VecType) $0 = size=2 {
[0] = "string"
[1] = "other string"
}
This is obviously not a great solution, since you have to have introduced these typedef's into your code in order to use them in the debugger. Further, you need to not just define them, but also use them, or the compiler will not emit them into the debug info. So if I left out line 11 above, I would have gotten:
(lldb) expr *(VecType *) hidden
error: use of undeclared identifier 'VecType'
we can use tensor's data() function to solve this question .
for example p (std::__1::string *)(tensor->buf_->data())
and why we can use data() function in lldb ?
I am using bazel to build some code. The code gives compilation error while doing dome matrix assignments.
typedef Eigen::Matrix<double,44,44> stateMat_t;
typedef Eigen::Matrix<double,44,44> stateTens_t[44]; //44 x 44 x 44
// bunch of other code...
typedef std::vector<stateMat_t> stateTensTab_t;
// bunch of other code...
stateTensTab_t fxxList;
stateTens_t fxx;
// bunch of other code
fxxList[j][k] = fxx[j];
//bunch of other code
I expect the code to compile successfully, but it gives the following error:
error: cannot convert 'Eigen::Matrix<double, 44, 44>' to 'Eigen::DenseCoeffsBase<Eigen::Matrix<double, 44, 44>, 1>::Scalar {aka double}' in assignment
fxxList[j][k] = fxx[j];
You are trying to assign a Matrix<double,44,44> to a double&, since that is what Matrix::operator[] returns (the operator where you pass k). Calling that operator alone should also fail, since stateMat_t is not a vector at compile time.
I'm getting the following error:
error: cannot convert 'std::basic_string<char>::iterator {aka __gnu_cxx::__normal
_iterator<char*, std::basic_string<char> >}' to 'const char*' for argument '1'
to 'int remove(const char*)'
For some reason, my program compiles perfectly when I'm working on a Mac... but once I use a Linux machine, this error pops up in more than one place.
Here's one of the instances where the error pops up:
SomeClass::SomeClass(string t, string art, Time dur) {
char chars[] = ",";
t.erase(std::remove(t.begin(), t.end(), chars[0]), t.end());
art.erase(std::remove(art.begin(), art.end(), chars[0]), art.end());
// Some more code ...
}
More specifically, the error is coming from this line:
t.erase(std::remove(t.begin(), t.end(), chars[0]), t.end());
Does anyone know how to approach this problem?
You forgot to #include <algorithm>, where std::remove is located. Without that, your compiler only knows about this std::remove (I get the same error with Visual C++ 14), which is defined in indirectly included <cstdio> header.
Different behavior among compilers is a result of different #include hierarchies of the standard library implementations.
I am not familiar with templates. I've just started learning it. Why I am getting errors in following program?
#include <iostream>
#include <string>
using std::cout;
using std::string;
template<class C>
C min(C a,C b) {
return a<b?a:b;
}
int main()
{
string a="first string";
string b="second string";
cout<<"minimum string is: "<<min(a,b)<<'\n';
int c=3,d=5;
cout<<"minimum number is: "<<min(c,d)<<'\n';
double e{3.3},f{6.6};
cout<<"minimum number is: "<<min(e,f)<<'\n';
char g{'a'},h{'b'};
cout<<"minimum number is: "<<min(g,h)<<'\n';
return 0;
}
Errors:
13 [Error] call of overloaded 'min(std::string&, std::string&)' is ambiguous
6 [Note] C min(C, C) [with C = std::basic_string<char>]
Please help me.
There are a two things going on here.
Your first problem is that you only included part of the error message. Here is a link to the code being complied in gcc and clang, and one of the resulting error messages (in full):
main.cpp:13:34: error: call to 'min' is ambiguous
cout<<"minimum string is: "<<min(a,b)<<'\n';
^~~
/usr/include/c++/v1/algorithm:2579:1: note: candidate function [with _Tp = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >]
min(const _Tp& __a, const _Tp& __b)
^
main.cpp:6:3: note: candidate function [with C = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >]
C min(C a,C b) {
^
there are two candidates. One at main.cpp:6:3 (line 6, character 3) and one at algorithm:2579:1 (line 2579, character 1).
One of them you wrote, and one of them in #include <algorithm>.
One of your header files included <algorithm> without you asking for it. The standard headers are allowed to do this, as annoying as it is sometimes.
In <algorithm> there is a std::min function template. As std::string is an instance of a template class in namespace std, the function template std::min is found via a process called "argument dependent lookup" or "Koenig lookup". (function overload candidates are searched for locally, and also in the namespaces of the arguments to the function, and in the namespaces of the template arguments to the arguments to the function, and in the namespaces of the things pointed to by the arguments of the function, etc.)
Your local function min is also found, as it is in the same namespace as the body of main.
Both are equally good matches, and the compiler cannot decide which one you want to call. So it generates an error telling you this.
Both gcc and clang do error: then a sequence of note:s. Usually all of the note:s after an error are important to understanding the error.
To fix this, try calling ::min (fully qualifying the call), or renaming the function to something else, or make your version a better match than std::min (tricky, but doable in some cases), or calling (min)(a,b). The last blocks ADL/Koenig lookup, and also blocks macro expansion (for example, if some OS has injected #define min macros into their system headers) (via # 0x499602D2).
You're running into a name collision with std::min. It is likely included in one of the other standard libary headers that you included, either <iostream> or <string>, my guess is probably the latter. The quick fix is to rename your function. For example, renaming it to mymin works fine. Demo
Problem
I got a bug report from user reporting a segfault in library I develop.
The minimal example of the faulty code is:
#include <map>
#include <string>
#include <iostream>
void f(std::map<std::string, std::string> m = {})
{
std::cout << m.size() << "\n";
for (const auto& s: m) {
std::cout << s.first << "->" << s.second <<"\n";
}
}
int main()
{
f();
}
When compiled with GCC (I tested 4.8.2 and 4.7.3) it correctly prints 0 as size of the container, but segfaults inside the loop (which shouldn't be executed at all).
Workarounds
However, I can fix the problem by changing the declaration to:
void f(std::map<std::string, std::string> m = std::map<std::string, std::string>{})
Copying the map works as well:
void f(std::map<std::string, std::string> mx = {})
{
auto m = mx;
std::cout << m.size() << "\n";
for (const auto& s: m) {
std::cout << s.first << "->" << s.second <<"\n";
}
}
Changing the parameter to const std::map<...>& also works.
GCC 4.9.1 works fine.
Clang also compiles and runs the code just fine. (even when using the same libstdc++ as failing gcc 4.8.2)
Working example: http://coliru.stacked-crooked.com/a/eb64a7053f542efd
Question
The map is definitely not in valid state inside the function (details bellow).
It looks like a GCC (or libstdc++) bug, but I want to be sure I'm not making some stupid mistake here.
It's hard to believe such a bug would stay in gcc for at least 2 major version.
So my question is: Is the way of initializing default std::map parameter wrong (and bug in my code) or is it a bug in stdlibc++ (or gcc)?
I'm not looking for workarounds (as I know what to do to make to code work)
When integrated in the application, the offending code executes fine on some computers (even when compiled with gcc 4.8.2) on some doesn't.
Details
I compile it using:
g++-4.8.2 -g -Wall -Wextra -pedantic -std=c++11 /tmp/c.cpp -o /tmp/t
Backtrace from gdb:
#0 std::operator<< <char, std::char_traits<char>, std::allocator<char> > (__os=..., __str=...) at /usr/src/debug/sys-devel/gcc-4.8.2/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:2758
#1 0x0000000000400f36 in f (m=std::map with 0 elements) at /tmp/c.cpp:9
#2 0x0000000000400fe0 in main () at /tmp/c.cpp:15
/tmp/c.cpp:9 is the line with std::cout << ...
ASAN reports:
AddressSanitizer: SEGV on unknown address 0xffffffffffffffe8
This seems like nullptr - 8
valgrind shows:
==28183== Invalid read of size 8
==28183== at 0x4ECC863: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.2/libstdc++.so.6.0.18)
==28183== by 0x400BD5: f(std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >) (c.cpp:9)
==28183== by 0x400C7F: main (c.cpp:15)
==28183== Address 0xffffffffffffffe8 is not stack'd, malloc'd or (recently) free'd
Looking at internal state of the map shows that the code really has to fail:
std::map::begin() in libstdc++ returns value of
this->_M_impl._M_header._M_parent
from it's internal representation, std::map::end() returns:
&this->_M_impl._M_header
gdb shows:
(gdb) print m._M_t._M_impl._M_header
$5 = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0x7fffffffd6d8, _M_right = 0x7fffffffd6d8}
(gdb) print &m._M_t._M_impl._M_header
$6 = (std::_Rb_tree_node_base *) 0x7fffffffd6a8
So value of begin() and end() are not the same (begin() is nullptr) as mandated by standard for empty std::map.
Looks like this bug was fixed in 4.8.3/4.9.0, the bug report which has a similar example and also seg-faults says:
The attached minimal testcase has the following function with
default-constructed default argument:
void do_something( foo f = {} )
{ std::cout << "default argument is at " << &f << std::endl;
}
The constructor for foo outputs its address; I got the following
output from a single run:
constructed foo # 0x7ffff10bdb7f
default argument is at 0x7ffff10bdb60
It shows that only 1 foo was constructed, and not at the same address
as that of the default argument. It's been a loooong week, but I can't
see anything wrong with the code. In the real code on which this was
based, a segfault was occurring when running the destructor of a foo
that was move-constructed from the default argument, because the
underlying memory was seemingly uninitialised.
We can see from a live example that 4.9.0 does not demonstrate this problem.
We can see this was intentional functionality from defect report 994 and the subsequent resolution N3217:
This paper presents detailed wording changes relative to the current
C++ Working Draft N3126 to implement brace-initializers for default
arguments for functions, as proposed in N3139 "An Incomplete Language
Feature" by Bjarne Stroustrup, thereby also addressing core issue 994.
This is also covered in the proposal N3139: An Incomplete Language Feature.
Interesting to note that Visual Studio also has a bug with respect to brace-initializers as default arguments which I think is still unresolved.