繁体   English   中英

Valgrind:抛出自定义异常时为“无效的读取大小1”

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM