【发布时间】:2012-09-12 22:36:51
【问题描述】:
我有 valgrind 3.6.0,我到处搜索,一无所获。
问题是,当我在使用 valgrind 时尝试访问浮点数时,会出现段错误,但是当我按原样运行程序时,没有 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 也访问浮点数时,我继续收到一个段错误信号。
这是我使用 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();(收到任何信号,Object 刚刚完成他的工作),我不会以任何方式出现段错误(就像 valgrind 一样)。
请不要告诉我“不要用 Control+C 等等等等来关闭你的程序……”这段代码用于记录程序可能出现的任何错误,而不会在发生段错误的情况下丢失数据,杀死它因为死锁或其他原因。
编辑:也许是一个 valgrind 错误(我不知道,在 google 上搜索但什么也没找到,不要杀我),也可以接受任何解决方法。
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)
【问题讨论】:
-
我不认为您的信号处理程序是异步安全的。不允许在信号处理程序中做复杂的事情。
-
解决方法:将
printf("%f", f);放在您的信号处理程序中。 -
Kerrek SB,我知道,但没有 valgrind 一切正常,所以我认为我没有做复杂的事情,因为工作。我需要将浮点数放在一个字符串中并尝试这样做:
sprintf(fl, "%.1g", f);但在访问浮点数时仍然在同一行崩溃,所以我认为这是浮点数的问题。我想我要把它乘以 10 并将其转换为一个整数。 -
“一切正常”是一条红鲱鱼。 UB 就是 UB,即使它看起来“不错”。
-
(您的信号处理程序上还缺少
extern "C"。)
标签: c++ floating-point segmentation-fault valgrind stringstream