c++ - Valgrind:抛出自定义异常时为 "invalid read size 1"

标签 c++ exception valgrind

我的程序工作正常,除非我在 valgrind 中运行它并使其抛出异常(我是故意这样做的,它取决于用户定义的参数)。

主要功能是:

int main(){
 try{
        // create objects
        // call function 
 }
 catch(std::exception const& e){
     std::cerr << "ERROR: " << e.what() << std::endl;
 }
 return 0;
}

并且我在代码中没有使用任何其他“try ... catch” block 。

我定义了自己的异常类:

#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” block 吗?我应该系统地捕获并重新抛出错误吗?

似乎需要为已经可以工作的东西添加很多代码,所以我的问题是:这是否意味着我有一个可能导致破坏的未定义行为,或者我可以忽略 valgrind 错误吗?

最佳答案

From what I understand, it returns an invalid pointer. But it compiles fine outside of valgrind and prints the right message.

这没有多大意义。你有未定义的行为,因此任何事情都可能发生(包括它似乎按预期工作)。

return msg.c_str(); 从局部变量返回指针,该变量在调用 TracedError::what() 后不再存在。这就是 valgrind 提示的原因。

您应该将 msg 设为异常类的成员变量,并在构造函数中构建消息字符串来解决此问题。

关于c++ - Valgrind:抛出自定义异常时为 "invalid read size 1",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33873321/

相关文章:

c++ - GetInput() SFML 的替代品?

c++ - Visual Studio Code : code not running for C++11

c# - 为什么 .NET 异常没有被 try/catch block 捕获?

exception - 错误-尝试在伪分布式模式下运行hbase吗?

c++ - Android NDK C++ 代码的内存调试工具

c - 由于某种原因分配的内存未释放 - C

c++ - 在二维伊辛模型上工作。 C++ 新手。我在第 23 行收到错误 "expected unqualified-id before ' {' token"

c++ - 使用 CGAL 框架在 C++ 中进行正常估计

testing - 如果不满足测试先决条件,则抛出异常或 Assert.Fail

C Valgrind 条件跳转或移动