[英]Valgrind: “invalid read size 1” when throwing custom exception
我的程序运行良好,除非在valgrind中运行它并使其引发异常(我故意这样做,它取决于用户定义的参数)。
主要功能是:
int main(){
try{
// create objects
// call function
}
catch(std::exception const& e){
std::cerr << "ERROR: " << e.what() << std::endl;
}
return 0;
}
而且我在代码中不使用任何其他“ try ... catch”块。
我定义了自己的Exception类:
#ifndef CUSTOMEXCEPTION_H_INCLUDED
#define CUSTOMEXCEPTION_H_INCLUDED
#include <exception>
class TracedError : public std::exception
{
protected:
int line_;
std::string file_;
std::string description;
public:
TracedError(std::string const& file, int line, std::string const& desc)
throw():
line_(line),
file_(file),
description(desc)
{}
virtual const char* what() const throw(){
std::string msg;
msg = "File: " + file_ + " Line: " + std::to_string(line_) + " Message: " + description;
return msg.c_str();
}
virtual ~TracedError() throw() {}
};
#endif // CUSTOMEXCEPTION_H_INCLUDED
我称这样的异常:
throw TracedError(__FILE__,__LINE__,"Message of the exception");
当我编译并运行程序时没有问题,这种形式下会出现一个异常:
ERROR: File: path/to/file.cpp Line: 106 Message: Message of the exception.
这正是我想要的。 但是当我用valgrind运行它时,我得到一个错误:
ERROR: ==12664== Invalid read of size 1
==12664== at 0x4C2CC02: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==12664== by 0x4ECED58: length (char_traits.h:263)
==12664== by 0x4ECED58: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (ostream:536)
==12664== by 0x441EC6: main (main.cpp:52)
==12664== Address 0x5a20b88 is 24 bytes inside a block of size 237 free'd
==12664== at 0x4C2B183: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==12664== by 0x4422E1: TracedError::what() const (TracedError.h:25)
==12664== by 0x441EA9: main (main.cpp:52)
==12664==
==12664== Invalid read of size 1
==12664== at 0x4C2CC14: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==12664== by 0x4ECED58: length (char_traits.h:263)
==12664== by 0x4ECED58: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (ostream:536)
==12664== by 0x441EC6: main (main.cpp:52)
==12664== Address 0x5a20b89 is 25 bytes inside a block of size 237 free'd
==12664== at 0x4C2B183: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==12664== by 0x4422E1: TracedError::what() const (TracedError.h:25)
==12664== by 0x441EA9: main (main.cpp:52)
==12664==
==12664== Syscall param write(buf) points to unaddressable byte(s)
==12664== at 0x5753940: __write_nocancel (syscall-template.S:81)
==12664== by 0x56DBD2C: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1302)
==12664== by 0x56DC4EE: new_do_write (fileops.c:537)
==12664== by 0x56DC4EE: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1384)
==12664== by 0x56D1E68: fwrite (iofwrite.c:43)
==12664== by 0x4ECE955: sputn (streambuf:451)
==12664== by 0x4ECE955: __ostream_write<char, std::char_traits<char> > (ostream_insert.h:50)
==12664== by 0x4ECE955: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (ostream_insert.h:101)
==12664== by 0x4ECED66: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (ostream:535)
==12664== by 0x441EC6: main (main.cpp:52)
==12664== Address 0x5a20b88 is 24 bytes inside a block of size 237 free'd
==12664== at 0x4C2B183: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==12664== by 0x4422E1: TracedError::what() const (TracedError.h:25)
==12664== by 0x441EA9: main (main.cpp:52)
==12664==
File: /home/ak/Documents/framework-v3/src/encoder.cpp Line: 106 Message: The evolution parameters are incorrect.
==12664==
==12664== HEAP SUMMARY:
==12664== in use at exit: 0 bytes in 0 blocks
==12664== total heap usage: 26 allocs, 26 frees, 1,292 bytes allocated
==12664==
==12664== All heap blocks were freed -- no leaks are possible
==12664==
==12664== For counts of detected and suppressed errors, rerun with: -v
==12664== ERROR SUMMARY: 114 errors from 3 contexts (suppressed: 0 from 0)
main.cpp:52引用此行:
std::cerr << "ERROR: " << e.what() << std::endl;
和TracedError.h:25引用此行:
return msg.c_str();
据我了解,它返回一个无效的指针。 但是它可以在valgrind之外很好地编译并输出正确的消息。
是因为我不在其他类/函数中使用“ try ... catch”块吗? 我应该系统地捕获并重新抛出错误吗?
似乎要为已经可用的东西添加很多代码,所以我的问题是:这是否意味着我有未定义的行为,可能会导致havock或我可以忽略valgrind错误?
据我了解,它返回一个无效的指针。 但是它可以在valgrind之外很好地编译并输出正确的消息。
那并不重要。 您有未定义的行为,因此任何事情都可能发生(包括看起来像预期的那样)。
return msg.c_str();
从局部变量返回指针,该局部变量在TracedError::what()
之后不再存在。 这就是valgrind抱怨的原因。
您应该使msg
成为异常类的成员变量,并在构造函数中构建消息字符串以解决此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.