gpt4 book ai didi

C++ float 和 valgrind 奇怪的行为

转载 作者:太空狗 更新时间:2023-10-29 23:07:35 24 4
gpt4 key购买 nike

我有 valgrind 3.6.0,我到处搜索但一无所获。

问题是,当我在使用 valgrind 时尝试访问 float 时,出现段错误,但是当我按原样运行程序时,没有 valgrind,一切都按预期进行。

这是一段代码:

class MyClass {
public:
void end() {
float f;
f = 1.23;
std::stringstream ss;
ss << f;
std::cout << ss.str();
}
};

extern "C" void clean_exit_on_sig(int sig) {
//Code logging the error
mc->end();
exit(1);
}

MyClass *mc;
int main(int argc, char *argv[]) {
signal(SIGINT , clean_exit_on_sig);
signal(SIGABRT , clean_exit_on_sig);
signal(SIGILL , clean_exit_on_sig);
signal(SIGFPE , clean_exit_on_sig);
signal(SIGSEGV, clean_exit_on_sig);
signal(SIGTERM , clean_exit_on_sig);
mc = new MyClass();
while(true) {
// Main program loop
}
}

当我按下 Control+C 时,程序会正确捕获信号并且一切正常,但是当我使用 valgrind 运行程序时,当我尝试执行此命令时 ss << f; // (Inside MyClass)抛出段错误:-/

我也试过:

std::string stm = boost::lexical_cast<std::string>(f);

但是当 boost 也访问 float 时,我继续收到段错误信号。

这是当我使用 boost 出现段错误时的回溯:

./a.out(_Z17clean_exit_on_sigi+0x1c)[0x420e72]
/lib64/libc.so.6(+0x32920)[0x593a920]
/usr/lib64/libstdc++.so.6(+0x7eb29)[0x51e6b29]
/usr/lib64/libstdc++.so.6(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_+0xd3)[0x51e8f43]
/usr/lib64/libstdc++.so.6(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES3_RSt8ios_basecd+0x19)[0x51e9269]
/usr/lib64/libstdc++.so.6(_ZNSo9_M_insertIdEERSoT_+0x9f)[0x51fc87f]
./a.out(_ZN5boost6detail26lexical_stream_limited_srcIcSt15basic_streambufIcSt11char_traitsIcEES4_E9lcast_putIfEEbRKT_+0x8f)[0x42c251]
./a.out(_ZN5boost6detail26lexical_stream_limited_srcIcSt15basic_streambufIcSt11char_traitsIcEES4_ElsEf+0x24)[0x42a150]
./a.out(_ZN5boost6detail12lexical_castISsfLb0EcEET_NS_11call_traitsIT0_E10param_typeEPT2_m+0x75)[0x428349]
./a.out(_ZN5boost12lexical_castISsfEET_RKT0_+0x3c)[0x426fbb]
./a.out(This line of code corresponds to the line where boost tries to do the conversion)

这是默认的字符串流转换:

./a.out(_Z17clean_exit_on_sigi+0x1c)[0x41deaa]
/lib64/libc.so.6(+0x32920)[0x593a920]
/usr/lib64/libstdc++.so.6(+0x7eb29)[0x51e6b29]
/usr/lib64/libstdc++.so.6(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_+0xd3)[0x51e8f43]
/usr/lib64/libstdc++.so.6(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES3_RSt8ios_basecd+0x19)[0x51e9269]
/usr/lib64/libstdc++.so.6(_ZNSo9_M_insertIdEERSoT_+0x9f)[0x51fc87f]
./a.out(This line of code corresponds to the line where I try to do the conversion)

a.out是我的程序,我这样运行 valgrind:valgrind --tool=memcheck ./a.out

另一个奇怪的事情是,当我调用 mc->end(); 时虽然程序运行良好(收到任何信号,对象刚刚完成他的工作),但我不会以任何方式出现段错误(与 valgrind 一样)。

请不要告诉我“不要用 Control+C blah blah... 关闭你的程序”这段代码用于记录程序可能出现的任何错误,而不会在出现段错误时丢失数据,将其杀死由于死锁或其他原因。

编辑:可能是一个 valgrind 错误(我不知道,在谷歌上搜索但什么也没找到,别杀了我),任何解决方法也将被接受。

EDIT2: 刚意识到 boost 也会调用 ostream(这里比使用 vim 更清楚:-/),将尝试 sprintf float 转换。

EDIT3:试过这个sprintf(fl, "%.1g", f);但仍然崩溃,回溯:

./a.out(_Z17clean_exit_on_sigi+0x40)[0x41df24]
/lib64/libc.so.6(+0x32920)[0x593a920]
/lib64/libc.so.6(sprintf+0x56)[0x5956be6]
./a.out(Line where sprintf is)

最佳答案

好的,经过几个小时的阅读和研究,我发现了问题,我将回答我自己的问题,因为没有人回答,只有@Kerrek SB [ https://stackoverflow.com/users/596781/kerrek-sb 的评论] ] 但我不能接受评论。 (谢谢)

就像在信号处理程序中一样简单,您只能安全地调用一堆函数:http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html

如果您调用一些非异步安全函数,它们可以工作,但并非总是如此。

如果您想在信号处理程序中调用非异步安全函数,您可以这样做:

  • 创建 2 个管道。 int pip1[2]; int pip2[2];管道(pip1);管道(pip2);
  • 创建一个新线程并让该线程等待从第一个管道接收一些数据 read(pip1[0], msg, 1);
  • 当调用信号处理程序时,使用write异步安全函数写入第一个管道write(pip1[1], "0", 1);
  • 然后使用 read(pip2[0], msg, 1);
  • 让信号等待第二个管道
  • 线程将醒来并完成他必须做的所有工作(在这种情况下将数据保存到数据库),之后,让线程将数据写入第二个管道 write(pip2[1], "0", 1);
  • 现在主线程将唤醒并以 _Exit(1) 或其他方式结束。

信息:

我正在使用 2 个管道,因为如果我写入一个管道并在之后读取它,那么第二个线程可能永远不会醒来,因为主线程已经读取了刚刚写入的数据。我正在使用辅助管道阻塞主线程,因为我不希望它在第二个线程保存数据时退出。

请记住,在修改共享资源时可能会调用信号处理程序,如果您的第二个线程访问该资源可能会遇到第二个段错误,因此在使用第二个线程访问共享资源时要小心(全局变量或别的东西)。

如果您正在使用 valgrind 进行测试并且不想在收到信号时收到“假”内存泄漏,您可以在退出 pthread_join(2ndthread, NULL)exit( 1) 而不是 _Exit(1)。这些是非异步安全函数,但至少您可以测试内存泄漏并使用信号关闭您的应用程序而不会收到“假”内存泄漏。

希望这对某人有帮助。再次感谢@Kerrek SB。

关于C++ float 和 valgrind 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12397072/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com