stack overflow on stepping into a function

1

I'm getting a stack overflow error when I step into a function in debug mode using VS 2015. Here's the exact message, in case that helps:

Unhandled exception at 0x0000000140D9F018 in TestProgram.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000000000213000).

The function I'm entering looks like this:

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;
    }
}

Here's what's confusing me:

  1. I'm stepping into the function, so I don't think there can be any recursion going on. When I get the stack overflow error, it's on the opening bracket of the function - none of the lines of the function are even getting called.
  2. When I comment out this line in the 'else if' section: cereal::XMLInputArchive arSettingsObject(ss, pSettings->XML_TAG); then not only does the stack overflow error go away, but the function runs as expected, executing the `if' block successfully (so it successfully creates a 'cereal::XMLInputArchive', loads it from the stringstream, etc).

In both cases (when the function runs, and when it causes a stack overflow), it's getting called with the same input parameter (about 300 chars of base64 encoded xml).

So, somehow, when I compile with all the code uncommented, I cause something to go wrong with the function's execution/memory allocation, but I don't understand what.

Oh yeah, in case this helps, the call stack has this on top when I get the stack overflow error:

TestProgram.exe!__chkstk()

Other than that, it looks the same as when the function runs successfully (that also leads me to think there's no recursion).

[Edit]

After searching for __chkstk(), I just found/read this SO article: What is the purpose of the _chkstk() function?

That's making me think that this is not a traditional stack overflow error, where I'm asking for too much memory, rather that something in the function is trying to reference an illegal place in memory, which is causing VS to report a stack overflow. But, I'm still not sure why/how that could happen if the function isn't even executing, since that block won't run.

Thanks in advance for any insight as to what could cause this type of behavior.

I have a bad feeling that I'm missing something fundamental about function calling.

c++
function
stack-overflow
asked on Stack Overflow Aug 16, 2018 by user3074363

1 Answer

1

Turns out that _chkstk() throws a stack overflow when you have exceeded the declared maximum stack size declared in an .exe build. Your solution then? Increase it. Though also consider removing the bit of redundancy in your code:

First, consider that upon entering the function, we need to ensure that there is enough space for all local variables of your function on the stack. Let's look at what those are:

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;
  }
}

Now consider that you find the _chkstk() variable on the call stack to begin with. This implies that this function allocates a lot of memory! That commenting out a single declaration resolves the problem points to the greedy memory culprit. But wait, you have two of these, and that you can get away with one implies that consolidating your duplicated declaration might pay dividends:

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;
  }
}

Although this changes the scope on arSettingsObject, it isn't a problem because the function terminates after the if/else statement and all return paths from where it is declared require it.

answered on Stack Overflow Aug 17, 2018 by OrderNChaos

User contributions licensed under CC BY-SA 3.0