简体   繁体   中英

Why do I get “Invalid read of size 8”? (Valgrind)

I already read similar posts on Stackoverflow but they do not solve my problem.

My problem

I get the following error message from Valgrind when I run the debug version of the executable with Valgrind.

==16631== Invalid read of size 8
==16631==    at 0x217890: std::__detail::__variant::_Uninitialized<long long, true>::_Uninitialized<long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:222)
==16631==    by 0x2178C9: std::__detail::__variant::_Variadic_union<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variadic_union<long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:342)
==16631==    by 0x2178FD: std::__detail::__variant::_Variant_storage<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:399)
==16631==    by 0x2156F0: std::__detail::__variant::_Copy_ctor_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:504)
==16631==    by 0x215716: std::__detail::__variant::_Move_ctor_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:532)
==16631==    by 0x21573C: std::__detail::__variant::_Copy_assign_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:592)
==16631==    by 0x215762: std::__detail::__variant::_Move_assign_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:649)
==16631==    by 0x215791: std::__detail::__variant::_Variant_base<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_base<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:701)
==16631==    by 0x213F29: std::variant<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::variant<0ul, long long const&, long long, void>(std::in_place_index_t<0ul>, long long const&) (variant:1398)
==16631==    by 0x213F6B: std::variant<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::variant<long long const&, void, void, long long, void>(long long const&) (variant:1369)
==16631==    by 0x20B8ED: tgbot::Endpoints::deleteMessage(long long const&, int const&) const (Endpoints.cpp:1957)
==16631==    by 0x2B17F6: ChatCleaner::run(std::shared_ptr<tgbot::Bot> const&) (ChatCleaner.cpp:40)
==16631==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==16631== 
==16631== 
==16631== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==16631==  Access not within mapped region at address 0x0
==16631==    at 0x217890: std::__detail::__variant::_Uninitialized<long long, true>::_Uninitialized<long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:222)
==16631==    by 0x2178C9: std::__detail::__variant::_Variadic_union<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variadic_union<long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:342)
==16631==    by 0x2178FD: std::__detail::__variant::_Variant_storage<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:399)
==16631==    by 0x2156F0: std::__detail::__variant::_Copy_ctor_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:504)
==16631==    by 0x215716: std::__detail::__variant::_Move_ctor_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:532)
==16631==    by 0x21573C: std::__detail::__variant::_Copy_assign_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:592)
==16631==    by 0x215762: std::__detail::__variant::_Move_assign_base<false, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_storage<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:649)
==16631==    by 0x215791: std::__detail::__variant::_Variant_base<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::_Variant_base<0ul, long long const&>(std::in_place_index_t<0ul>, long long const&) (variant:701)
==16631==    by 0x213F29: std::variant<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::variant<0ul, long long const&, long long, void>(std::in_place_index_t<0ul>, long long const&) (variant:1398)
==16631==    by 0x213F6B: std::variant<long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::shared_ptr<tools::InputFile> >::variant<long long const&, void, void, long long, void>(long long const&) (variant:1369)
==16631==    by 0x20B8ED: tgbot::Endpoints::deleteMessage(long long const&, int const&) const (Endpoints.cpp:1957)
==16631==    by 0x2B17F6: ChatCleaner::run(std::shared_ptr<tgbot::Bot> const&) (ChatCleaner.cpp:40)
==16631==  If you believe this happened as a result of a stack
==16631==  overflow in your program's main thread (unlikely but
==16631==  possible), you can try to increase the size of the
==16631==  main thread stack using the --main-stacksize= flag.
==16631==  The main thread stack size used in this run was 8388608.
==16631== 
==16631== HEAP SUMMARY:
==16631==     in use at exit: 317,149 bytes in 4,488 blocks
==16631==   total heap usage: 1,171,900 allocs, 1,167,412 frees, 359,098,054 bytes allocated
==16631== 
==16631== LEAK SUMMARY:
==16631==    definitely lost: 0 bytes in 0 blocks
==16631==    indirectly lost: 0 bytes in 0 blocks
==16631==      possibly lost: 0 bytes in 0 blocks
==16631==    still reachable: 317,045 bytes in 4,487 blocks
==16631==         suppressed: 104 bytes in 1 blocks
==16631== Reachable blocks (those to which a pointer was found) are not shown.
==16631== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==16631== 
==16631== For lists of detected and suppressed errors, rerun with: -s
==16631== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Speicherzugriffsfehler (Speicherabzug geschrieben)

The suitable source code

"m_msgs_to_delete" is a static vector in the class ChatCleaner.

32void ChatCleaner::run(const tgbot::Bot::ptr &bot) noexcept
33{
34  if(!m_msgs_to_delete.empty())
35  {
36      //Reverse to have the oldest message at the end.
37      std::reverse(m_msgs_to_delete.begin(), m_msgs_to_delete.end());
38
39      //Delete the message.
40      bot->get_endpnts()->deleteMessage(m_msgs_to_delete.at(m_msgs_to_delete.size() - 1)->chat->id, m_msgs_to_delete.at(m_msgs_to_delete.size() - 1)->message_id);
41      m_msgs_to_delete.pop_back();
42
43      //Reverse again.
44      std::reverse(m_msgs_to_delete.begin(), m_msgs_to_delete.end());
45
46      m_last_time = tools::Tools::get_time();
47      m_msgs_to_delete.shrink_to_fit();
48  }
49}
1953    bool Endpoints::deleteMessage(const long long &chat_id, const int &message_id) const noexcept
    {
        //HTTP arguments
        std::vector<tools::HttpArg> http_args;
1957        http_args.push_back(tools::HttpArg("chat_id", chat_id));
        http_args.push_back(tools::HttpArg("message_id", message_id));

        tools::HttpClient http_client("https://api.telegram.org/bot" + m_token + "/deleteMessage", http_args);
        std::string json = http_client.send_post_req_multipart().m_body;

1963        rapidjson::Document doc;
        doc.Parse(json.c_str());

        if(doc.IsObject())
            if(doc.HasMember("result"))
                if(doc["result"].IsBool())
1969                    return doc["result"].GetBool();
                else
                    tools::Tools::write_err_log(Messages::field_does_not_contain_bool("result"));
            else
                tools::Tools::write_err_log_tmp(Messages::field_non_existent("result"));
        else
            tools::Tools::write_err_log(Messages::server_resp_not_json_object);
1976
1977        return false;
1978    }

From what I see the error occurs in line 40 of the snippet above as that is an excerpt from the file ChatCleaner.cpp. This line accesses a vector which can totally be the error as users with similar problems on Stackoverflow also had problems with vector or array accessing. Unfortunately, I cannot see what I did wrong. This error error happens absolutely arbitrarily and I cannot reproduce it.

Additional notes that might help

  • The code is from a my chat bot for Telegram which runs 24/7.
  • The error can happen a few minutes after starting the software or after days or weeks.
  • The vector contains std::shared_ptr<> of sent messages which shall be deleted after a while.
  • I already checked whether the vector content may be broken which was not the case when the error occurred. The chat and message ID were totally fine. I highly assume that is just a memory accessing problem but I cannot figure out the soure of the problem.

Question

What is the cause of the problem?

I finally found the source of the problem with the help of the hints @cdhowie gave. The member variable "chat" of the Message object caused the problem since as you can see here

if(doc.HasMember("chat"))
{
    if(doc["chat"].IsObject())
        chat = std::make_shared<Chat>(tools::Tools::get_json_as_string(doc["chat"]));
    else
        tools::Tools::write_err_log(Messages::field_does_not_contain_json_obj("chat"));
}

this part of the Message constructor only creates a chat instance if the passed HTTP response body contains the proper field. Therefore, this member access m_msgs_to_delete.at(m_msgs_to_delete.size() - 1)->chat->id in line 40 of ChatCleaner.cpp called a null pointer as "chat" does not exist on the heap in this case.

PS: The object doc above comes from the library rapidjson. The definition is rapidjson::Document doc; . Its purpose is parsing JSON objects and making data accessible. The whole source code is from my Telegram chat bot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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