C++ lambda "__closure" address in gdb - c++

I understand that there's a hidden closure class in C++11 or above for lambdas. But
when is the value of __closure when debugging in gdb 0x0 when calling a lambda? What does that mean?
// a.cpp
#include <iostream>
using std::cout;
int main() {
auto l1 = []() {
cout << "lambda 1\n";
};
auto l2 = []() {
cout << "lambda 2\n";
};
l1();
l2();
using F = void (*)();
F lv = l2;
lv();
}
In gdb:
Breakpoint 1, <lambda()>::operator()(void) const (
__closure=0x7fffffffd83e) at a.cpp:7
7 cout << "lambda 1\n";
(gdb) c
Continuing.
lambda 1
Breakpoint 2, <lambda()>::operator()(void) const (
__closure=0x7fffffffd83f) at a.cpp:10
10 cout << "lambda 2\n";
(gdb) c
Continuing.
lambda 2
Breakpoint 2, <lambda()>::operator()(void) const (__closure=0x0)
at a.cpp:10
10 cout << "lambda 2\n";
(gdb) c
Continuing.
lambda 2
[Inferior 1 (process 27152) exited normally]
g++ & gdb:
$ g++ --version
g++ (GCC) 8.2.0
$ g++ -g -O0 -std=c++17 a.cpp -o a
$ gdb --version
GNU gdb (GDB) 8.1.1

Related

problem internal to GDB has been detected and debugging session dies in multi-thread environment

My test code is like this:
#include <iostream>
#include <string>
#include <thread>
#include <unistd.h>
using namespace std;
class ns_string {
public:
ns_string(string s) : _s(s) {}
static ns_string make_ns_string(const string &s) {
return ns_string(s);
}
string ns() const { return _s; }
private:
string _s;
};
void f2(string s) {
cout << "f2:" << s << endl;
}
void thread_func() {
while (1) {
cout << "------------------ another thread -> ";
f2("thread_func");
sleep(5);
}
}
void f(int i, const ns_string& name) {
cout << i << ", " << name.ns() << endl;
f2(name.ns());
}
int main(int argc,char* argv[]) {
thread t(thread_func);
for (int i=0; i<10; i++) {
f(i, ns_string::make_ns_string(std::to_string(i)));
}
t.join();
return 0;
}
I want to set a breakpoint when f2 parameter s == "4".
I do that via b f2 if strcmp(s.c_str(), "4") == 0.
Here're three cases that I experiment.
GDB version is 11.1
case 1
DONOT start thread_func. Everything is ok. The program stops when s=="4"
(gdb) r
0, 0
f2:0
1, 1
f2:1
2, 2
f2:2
3, 3
f2:3
4, 4
Breakpoint 1, f2 (s="4") at gdb-crash.cc:21
21 cout << "f2:" << s << endl;
case 2
Start thread_func, but DONOT call f2. gdb outputs:
(gdb) r
[New Thread 0xffffbf17c1c0 (LWP 20299)]
------------------ another thread -> 0, 0
Error in testing breakpoint condition:
Unable to fetch general registers.: No such process.
An error occurred while in a function called from GDB.
Evaluation of the expression containing the function
(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str() const) will be abandoned.
When the function is done executing, GDB will silently stop.
Selected thread is running.
(gdb) c
Continuing.
f2:0
1, 1
f2:1
2, 2
f2:2
3, 3
f2:3
4, 4
Thread 1 "a.out" hit Breakpoint 1, f2 (s="4") at gdb-crash.cc:21
21 cout << "f2:" << s << endl;
However I try to continue, it still can stop at s=="4.
case 3
Start the thread_func, and call f2
Program die. gdb outputs:
Error in testing breakpoint condition:
The program stopped in another thread while making a function call from GDB.
Evaluation of the expression containing the function
(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str() const) will be abandoned.
When the function is done executing, GDB will silently stop.
[Switching to Thread 0x7ffff7a47740 (LWP 1832)]
Thread 1 "a.out" hit Breakpoint 1, f2 (s="0") at a.cc:30
30 cout << "f2:" << s << endl;
Missing separate debuginfos, use: dnf debuginfo-install libgcc-11.2.1-9.fc34.x86_64 libstdc++-11.2.1-9.fc34.x86_64
../../gdb/infcall.c:1284: internal-error: value* call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*): Assertion `call_thread->thread_fsm == sm' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Obviously different threads access f2, which confuses gdb for some reason.
As a debugger, I don't care about which thread stops at that breakpoint. I only care about gdb makes it stop when my condition is met. How should I acheive that in multi-thread situation ?
This is a bug in GDB. Reproduced using current GDB trunk and GDB-10.0.
Assuming you are using g++ to build the code, here is a workaround:
(gdb) b f2 if s._M_dataplus._M_p[0] == '4' && s._M_dataplus._M_p[1] == '\0'
The most likely reason for the bug is that calling s.c_str() requires that the inferior (being debugged) program be resumed, and while it's running to evaluate s.c_str() another thread hits the breakpoint, causing GDB to become confused.
Similar (but not identical) bug.

this_thread / chrono has not been declared

I have checked many StackOverflow posts, but no answers solve my problem.
I get 2 errors:
g++ .\main.cpp -fopenmp -o test
.\main.cpp:12:14: error: 'std::this_thread' has not been declared
12 | std::this_thread::sleep_for(chrono::seconds(20000) );
.\main.cpp:12:37: error: 'chrono' has not been declared
12 | std::this_thread::sleep_for(chrono::seconds(20000) );
My current G++ version is:
g++.exe (MinGW.org GCC Build-2) 9.2.0
The code is:
#include <iostream>
#include <chrono>
#include <thread>
#include <omp.h>
int main()
{
omp_set_num_threads(4);
#pragma omp parallel
{
std::this_thread::sleep_for(chrono::seconds(20000) );
std::cout << "Number of available threads: " << omp_get_num_threads() << std::endl;
std::cout << "Current thread number: " << omp_get_thread_num() << std::endl;
std::cout << "Hello, World!" << std::endl;
}
return 0;
}
I have already tried -std=c++11 from 11 & 14 & 17.
I'm not sure it's right but about your second error can you replace it with
std::this_thread::sleep_for(chrono::seconds(20000) );
to
std::this_thread::sleep_for(std::chrono::seconds(20000));
I think the first error depends from second, but I'm not sure.

Variable Not In Scope for Lambda

I'm trying to diagnose a timing issue on a multi-core processor [Xeon Silver]. I think that the clocks have not been configured or synced between the processor. I'm using Eli Bendersky's [credited in the code snippet] threading examples to build a test instrument. I have made three changes. I made made the sleep occur first, and I added a call to std::chrono::system_clock::now() and tried to print it out. I'm building with gcc 4.8.5 on CentOS 7.5.
The code is as follows:
// // Eli Bendersky [http://eli.thegreenplace.net]
// This code is in the public domain.
#include <algorithm>
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <pthread.h>
int main(int argc, const char** argv) {
unsigned num_cpus = std::thread::hardware_concurrency();
std::cout << "Launching " << num_cpus << " threads\n";
// A mutex ensures orderly access to std::cout from multiple threads.
std::mutex iomutex;
std::vector<std::thread> threads(num_cpus);
for (unsigned i = 0; i < num_cpus; ++i)
{
threads[i] = std::thread([&iomutex, i]
{
// Simulate important work done by the tread by sleeping for a bit...
std::this_thread::sleep_for(std::chrono::milliseconds(200));
{
std::chrono::time_point ti = std::chrono::system_clock::now();
// Use a lexical scope and lock_guard to safely lock the mutex only for
// the duration of std::cout usage.
std::lock_guard<std::mutex> iolock(iomutex);
std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch() << "\n";
}
});
}
for (auto& t : threads) {
t.join();
}
return 0;
}
I build with make:
CXX = g++
CXXFLAGS = -std=c++11 -Wall -O3 -g -DNDEBUG -pthread
LDFLAGS = -lpthread -pthread
clock-check: clock-check.cpp
$(CXX) $(CXXFLAGS) $^ -o $# $(LDFLAGS)
GCC gives me the following error:
[user#sbc1 concur]$ make clock-check
g++ -std=c++11 -Wall -O3 -g -DNDEBUG -pthread clock-check.cpp -o clock-check -lpthread -pthread
clock-check.cpp: In lambda function:
clock-check.cpp:32:67: error: ‘ti’ was not declared in this scope
std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch() << "\n";
^
make: *** [clock-check] Error 1
ti is clearly in the same block scope as the print statement, and I'm baffled why the compiler is complaining. I have not found any restrictions on variables local to the lambda. Most of what I have found has been references to captures.
Your problem lies in this line:
std::chrono::time_point ti = std::chrono::system_clock::now();
std::chrono::time_point expect a type argument (e.g. std::chrono::time_point<std::chrono::system_clock>)
Prefer to use auto in this case:
auto ti = std::chrono::system_clock::now();
Then, you'll have an error since you try to output a std::chrono::duration in an output stream.
You should do:
std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch().count() << "\n";
It seems to be a bug in older gcc versions. With gcc 10.1 (--std=c++11) I get the error:
<source>: In lambda function:
<source>:23:34: error: missing template arguments before 'ti'
23 | std::chrono::time_point ti = std::chrono::system_clock::now();
| ^~
<source>:27:67: error: 'ti' was not declared in this scope; did you mean 'i'?
27 | std::cout << "Thread #" << i << " hit its clock at: " << ti.time_since_epoch() << "\n";
| ^~
|
The error about the missing template parameter (which is missing with gcc 4.5.8) on the declaration explains the second error.
Strangely gcc 4.8.5 with -std=c++11 happily compiles the code if you remove the line with std::cout: https://godbolt.org/z/6LREHF
Class template deduction is not available until c++17, so you need to specify your template parameters for chrono::timepoint. Alternatively, use auto:
auto ti = std::chrono::system_clock::now();
Furthermore, you attempt to stream a chrono::duration type, which is not possible. Use ti.time_since_epoch().count().
Live example

Why tcmalloc don't print function name, which provided via dlopen

I have next some project:
main.cpp
#include <iostream>
#include <cstddef>
#include <dlfcn.h>
int main()
{
void* handle = dlopen("./shared_libs/libshared.so", RTLD_LAZY);
if (NULL == handle)
{
std::cerr << "Cannot open library: " << dlerror() << '\n';
return -1;
}
typedef int (*foo_t)(const std::size_t);
foo_t foo = reinterpret_cast<foo_t>(dlsym(handle, "foo"));
const char* dlsym_error = dlerror();
if (dlsym_error)
{
std::cerr << "Cannot load symbol 'foo': " << dlsym_error << '\n';
dlclose(handle);
return -2;
}
std::cout << "call foo" << std::endl;
foo(10);
dlclose(handle);
return 0;
}
shared.cpp:
#include <cstddef>
#include <iostream>
extern "C"
{
int foo(const std::size_t size)
{
int b = size / size;
int* a = new int[size];
std::cout << "leaky code here" << std::endl;
}
}
and Makefile:
all:
g++ -fPIC -g -c shared.cpp
g++ -shared -o shared_libs/libshared.so -g shared.o
g++ -L shared_libs/ -g main.cpp -ldl
I use tcmalloc for debug this test program, which load dynamically libshared.so:foo and execute it.run command:
LD_PRELOAD=/usr/local/lib/libtcmalloc.so HEAPCHECK=normal ./a.out
The 1 largest leaks:
Using local file ./a.out.
Leak of 40 bytes in 1 objects allocated from:
# 7fe3460bd9ba 0x00007fe3460bd9ba
# 400b43 main
# 7fe346c33ec5 __libc_start_main
# 400999 _start
# 0 _init
Why I get address 0x00007fe3460bd9ba instead of line in foo function?
please help
P.s. I tried to use gdb with LD_PRELOAD=.../tcmalloc.so, but I get:
"Someone is ptrace()ing us; will turn itself off Turning perftools heap leak checking off"
Try removing dlclose call.
It's known issue that heap checker & profilers can't handle unloaded
shared objects.

C++: gcc 4.2.1 gives program which segfaults, not on linux

The following simple program segfaults on my mac (Lion) running gcc 4.2.1:
#include <iostream>
using namespace std;
struct A{
friend std::ostream& operator << (std::ostream& os, const A& a) {
os << 3 << endl;
}
};
template <typename T>
T f() { return T();}
int f() { return 2;}
int main() {
cout << f() << endl;
A a= f<A>();
cout << a << endl;
}
When I run the program, I get:
./a.out
2
3
Segmentation fault: 11
When I do a stacktrace, I get:
(gdb) run
Starting program: a.out
unable to read unknown load command 0x24
unable to read unknown load command 0x26
2
3
Program received signal SIGSEGV, Segmentation fault.
0x00007fff8b84fa49 in ?? ()
(gdb) bt
#0 0x00007fff8b84fa49 in ?? ()
#1 0x00007fff665c1ae8 in ?? ()
#2 0x0000000000000000 in ?? ()
The backtrace has no useful information (anyone know why?). This works
fine in linux.
Let's make it clearer what happens
(cout << a) << endl;
You forgot a return in your operator<<.