簡體   English   中英

進入函數時堆棧溢出

[英]stack overflow on stepping into a function

當我使用 VS 2015 在調試模式下進入一個函數時,出現堆棧溢出錯誤。這是確切的消息,以防萬一:

TestProgram.exe 中 0x0000000140D9F018 處未處理的異常:0xC00000FD:堆棧溢出(參數:0x0000000000000001,0x0000000000213000)。

我輸入的函數如下所示:

void CGUITaskRequest::DecodeAndDeserializeSettings(const std::string& sEncodedSettingsString)
{
    auto sDecoded = string_functions::base64_decode(sEncodedSettingsString);
    std::stringstream ss(sDecoded);

    if (m_eType == ETaskTypes::FILE && m_eSubtype == ETaskSubtypes::OPEN) {
        auto pSettings = std::make_shared<CModSettingsFileImport>();
        cereal::XMLInputArchive arSettingsObject(ss, pSettings->XML_TAG);   
        pSettings->load(arSettingsObject);
        m_ptrSettings = pSettings;
    }
    else if (m_eType == ETaskTypes::META && m_eSubtype == ETaskSubtypes::STATUS) {
        auto pSettings = std::make_shared<SMetaStatusSettings>();                   
        cereal::XMLInputArchive arSettingsObject(ss, pSettings->XML_TAG); // <- line I comment out to run successfully  
        pSettings->load(arSettingsObject);
        m_ptrSettings = pSettings;
    }
}

這是讓我困惑的地方:

  1. 步入功能,所以我不認為有可能是任何遞歸回事。 當我收到堆棧溢出錯誤時,它位於函數的左括號上 - 甚至沒有調用函數的任何行。
  2. 當我在“else if”部分注釋掉這一行時: cereal::XMLInputArchive arSettingsObject(ss, pSettings->XML_TAG); 然后不僅堆棧溢出錯誤消失了,而且該函數按預期運行,成功執行了 `if' 塊(因此它成功地創建了一個 'cereal::XMLInputArchive',從字符串流中加載它,等等)。

在這兩種情況下(當函數運行時,以及當它導致堆棧溢出時),都會使用相同的輸入參數(大約 300 個字符的 base64 編碼 xml)調用它。

因此,不知何故,當我在所有代碼未注釋的情況下進行編譯時,我會導致函數的執行/內存分配出現問題,但我不明白是什么。

哦,是的,如果這有幫助,當我收到堆棧溢出錯誤時,調用堆棧會將其放在最上面:

TestProgram.exe!__chkstk()

除此之外,它看起來與函數成功運行時相同(這也讓我認為沒有遞歸)。

[編輯]

在搜索 __chkstk() 之后,我剛剛找到/閱讀了這篇 SO 文章: _chkstk() 函數的目的是什么?

這讓我認為這不是傳統的堆棧溢出錯誤,我要求太多內存,而是函數中的某些內容試圖引用內存中的非法位置,這導致 VS 報告堆棧溢出。 但是,如果函數甚至沒有執行,我仍然不確定為什么/如何發生這種情況,因為該塊不會運行。

預先感謝您對可能導致此類行為的任何見解。

我有一種不好的感覺,我錯過了一些關於函數調用的基本知識。

事實證明,當您超過 .exe 版本中聲明的最大堆棧大小時_chkstk()會引發堆棧溢出 你的解決方案呢? 增加它 雖然也可以考慮刪除代碼中的冗余位:

首先,考慮在進入函數時,我們需要確保堆棧上有足夠的空間用於函數的所有局部變量。 讓我們看看那些是什么:

void CGUITaskRequest::DecodeAndDeserializeSettings(const std::string& sEncodedSettingsString)
{
  /* two variables here */
  auto sDecoded = string_functions::base64_decode(sEncodedSettingsString);
  std::stringstream ss(sDecoded);

  if (m_eType == ETaskTypes::FILE && m_eSubtype == ETaskSubtypes::OPEN) {
    /* two more variables here */
    auto pSettings = std::make_shared<CModSettingsFileImport>();
    cereal::XMLInputArchive arSettingsObject(ss, pSettings->XML_TAG);   
    pSettings->load(arSettingsObject);
    m_ptrSettings = pSettings;
  }
  else if (m_eType == ETaskTypes::META && m_eSubtype == ETaskSubtypes::STATUS) {
    /* and a final pair */
    auto pSettings = std::make_shared<SMetaStatusSettings>();                   
    cereal::XMLInputArchive arSettingsObject(ss, pSettings->XML_TAG); // <- line I comment out to run successfully  
    pSettings->load(arSettingsObject);
    m_ptrSettings = pSettings;
  }
}

現在考慮在調用堆棧上找到_chkstk()變量作為開始。 這意味着該函數分配了大量內存 注釋掉單個聲明解決了這個問題指向貪婪的內存罪魁禍首。 但是等等,你有兩個,你可以逃脫一個意味着合並你重復的聲明可能會帶來好處:

void CGUITaskRequest::DecodeAndDeserializeSettings(const std::string& sEncodedSettingsString)
{
  auto sDecoded = string_functions::base64_decode(sEncodedSettingsString);
  std::stringstream ss(sDecoded);
  /* single declaration*/
  cereal::XMLInputArchive arSettingsObject;
  if (m_eType == ETaskTypes::FILE && m_eSubtype == ETaskSubtypes::OPEN) {
    auto pSettings = std::make_shared<CModSettingsFileImport>();
    arSettingsObject = cereal::XMLInputArchive(ss, pSettings->XML_TAG);   
    pSettings->load(arSettingsObject);
    m_ptrSettings = pSettings;
  }
  else if (m_eType == ETaskTypes::META && m_eSubtype == ETaskSubtypes::STATUS) {
    auto pSettings = std::make_shared<SMetaStatusSettings>();                   
    arSettingsObject = cereal::XMLInputArchive(ss, pSettings->XML_TAG); // <- line I comment out to run successfully  
    pSettings->load(arSettingsObject);
    m_ptrSettings = pSettings;
  }
}

盡管這會更改arSettingsObject的范圍,但這不是問題,因為該函數在 if/else 語句之后終止,並且聲明它的所有返回路徑都需要它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM