main.cpp
#include <cinttypes>
#include <cstdlib>
#include <iostream>
#include <ostream>
#include <fstream>
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#define CHOSEN_CLOCK std::chrono::high_resolution_clock
// class Timer below derived from:
// https://raw.githubusercontent.com/99x/timercpp/refs/heads/master/timercpp.h
// https://www.fluentcpp.com/2018/12/28/timer-cpp/
// https://stackoverflow.com/q/21057676
class Timer {
std::atomic<bool> active{true};
public:
std::chrono::time_point<CHOSEN_CLOCK> timer_entry_ts; // SO:31497531
template<typename Function>
void setInterval(Function function, int interval);
void stop();
};
template<typename Function>
void Timer::setInterval(Function function, int interval) {
active = true;
std::thread t([=]() {
while(active.load()) {
timer_entry_ts = CHOSEN_CLOCK::now();
function();
if(!active.load()) return;
std::this_thread::sleep_until(timer_entry_ts + std::chrono::milliseconds(interval));
}
});
t.detach(); // it seems this causes "terminate called after throwing an instance of 'std::system_error' ; what(): Unknown error 1992278736"; if we do a -static linkage in build on Linux
}
void Timer::stop() {
active = false;
}
Timer mtimer;
std::chrono::time_point<CHOSEN_CLOCK> last_entry_ts{};
void timer_function(void)
{
long long int delta_micros = std::chrono::duration_cast<std::chrono::microseconds>(mtimer.timer_entry_ts-last_entry_ts).count();
printf("%7.3f ms\n", delta_micros/1000.0f);
last_entry_ts = mtimer.timer_entry_ts;
}
int main(const int argc, char** argv)
{
(void)argc; // warning: unused parameter
(void)argv; // warning: unused parameter
static_cast<void>(pthread_create);
static_cast<void>(pthread_cancel);
#ifdef _GLIBCXX_HAS_GTHREADS
printf("_GLIBCXX_HAS_GTHREADS is defined.\n");
#else
printf("_GLIBCXX_HAS_GTHREADS is NOT defined!\n");
#endif
last_entry_ts = CHOSEN_CLOCK::now();
mtimer.setInterval(timer_function, 25); // repeat timer_function at 25 ms period
std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // wait for 2 seconds
mtimer.stop();
printf("Thread stopped\n");
std::exit(EXIT_SUCCESS);
}
我使用以下方式构建此代码:
mkdir build && cd build
cmake ../ -DCMAKE_BUILD_TYPE=Debug -G "Unix Makefiles"
make
...我都在建造它
Mingw64(在Windows 10下),我有g++.exe (Rev3, Built by MSYS2 project) 14.2.0
raspberry pi 3b+上的raspbian伸展,我有g++ (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516
如果我按发布的代码构建代码,那么我可以看到在两个平台上的螺纹
timer_function
target_link_libraries(myProject PUBLIC -static)
中未接受的(启用),并且重建项目 - 然后它在mingw64/windows中再次起作用,但是它在raspbian上失败了:CMakeLists.txt
现在,很不幸,我会发现“未知错误1995920080”,所以我无法进一步研究它。但是,“ 0.202 ms”打印输出告诉我$ ./myProject
_GLIBCXX_HAS_GTHREADS is defined.
0.202 ms
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error 1995920080
Aborted
timer_function
确认
objdump -S ./myProject | less
似乎调用t.detach();
-并且使用
_ZNSt6thread6detachEv
可以在该功能上设置一个断点,但是
gdb --args ./myProject
不允许我踏上它,甚至不在tui模式下(它说“ [没有可用的可用源)”);我只能说,一旦我在敲击该断点后按gdb
tep,我就会得到上述错误:
s
(注意:我在这里看到Https://github.com/gcc-mirror/gcc/blob/73987e69/libstdc%2b%2b%2b%2b--v3/include/include/cits/std_thread.hread.hpread.hpread.h#l324
可能最终是
gdb
环境)
任何想法,我如何才能在raspbian strave上获得此示例的构建?
您到达
(gdb) b _ZNSt6thread6detachEv
Breakpoint 1 at 0x612b0
(gdb) r
...
_GLIBCXX_HAS_GTHREADS is defined.
[New Thread 0x76ffc2d0 (LWP 32461)]
1.260 ms
Thread 1 "myProject" hit Breakpoint 1, 0x000612b0 in std::thread::detach() ()
(gdb) s
Single stepping until exit from function _ZNSt6thread6detachEv,
which has no line number information.
24859.580 ms
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error 1996473040
Thread 1 "myProject" received signal SIGABRT, Aborted.
raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x000b6eb8 in abort ()
#2 0x00000020 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
的尽头并退出程序,而无需确保实际停止背景线程。当其他线程运行时,您不能仅仅从
detach()
退出;发出停止线程的信号已足够,因此您需要更改
inline void thread::detach() { std::__throw_system_error(EINVAL); }
代码以等待线程停止或提供其他机制(例如,通过返回_GLIBCXX_HAS_GTHREADS
对象并调用
-static
。