c++ - 这个 StackOverFlowException 是否需要指针才能正常工作?

标签 c++ visual-c++

我制作了一个程序,通过读取 .txt 文件来搜索回文,然后将输出放到一个单独的 .txt 文件中。

对于大约 50 个左右的字符,它可以正常工作。但是,如果我将大量单词复制并粘贴到 .txt 文件中以供其读取,则在运行时它会说“进程因 StackOverFlowException 而终止”。然后它打开一个名为 chkstk.asm 的文件,并有一个箭头指向一个叫做“test dword ptr [eax], eax ; probe page”的东西。接下来出现一个带有中断和继续选项的框,并显示“palindrone.exe 中发生类型为‘System.StackOverflowException’的未处理异常”

我目前正在努力改变周围的事物以使用指针等,并可能将事物存储在 vector 中。但是,我仍然不确定错误的原因是什么,我想知道它为什么会起作用以及需要更改什么以便我可以让它读取和处理大块文本。没有指针是它工作不正常的原因吗?

#include <iostream>
#include <string>
#include <ctype.h>
#include <iterator>
#include <algorithm>
#include <fstream>

using namespace std;

/**
    Recursivly reverses a string
    @ param word, the word being entered
    @ last_char, the last character currently in the string
    @ go, the recursive function to return the character and continue inside itself
**/
string string_reverse(string word)
{
    if (word.length() - 1 > 0)
    {
        char last_char = word[word.length()-1];
        word.erase(word.length()-1);
        string go = string_reverse(word);
        return go.insert(0, 1, last_char);
    }
    else  
        return word.substr(0,1);
}

/**
@param in, the input as the original string
@param la, the reverse string
**/
bool equals(string in, string la)
{
    if(in == la)
        return true;
    else 
        return false;
}

/**
processes the pal
**/
void process_pal(ofstream &outfile, string in, string la, bool sam)
{
    if (sam == true)
    {
        outfile << in << " EQUAL to backwards: " << la << "\n";
    }
    else
        outfile << in << " NOT equal to backwards: " << la << "\n";
}

/**
    Removes all Numbers, white spaces, and invalid symbols with !isalpha
    @param sentence, the sentence being entered
    @ it, the iterator to iterator through the sentence checking for invlaid sysmbols
**/
string remover(string sentence)
{
    string::iterator it = sentence.begin();

    while (it != sentence.end())
    {
         while( it != sentence.end() && !isalpha(*it))
         {
             it = sentence.erase(it);
         }
         if (it != sentence.end())
             ++it;
    }
return sentence;
}

/**
    Increments to find paladrome by starting at 3 from 0, then moving right 1 by 3 each time util
    it goes to the end. Once it hits the end, it will increment by four and do the same thing till
    it has become the full length of the text.
**/
void find_pal(ofstream &outfile, string input, int pos, int lin)
{
    int max_length = input.length()+1;
    int pos_last = max_length - lin;
    if(lin < input.length()){
        string sub_fwrd = input.substr(pos,lin);
        string sub_bck = string_reverse(sub_fwrd);
        bool same = equals(sub_fwrd, sub_bck);
        process_pal(outfile, sub_fwrd, sub_bck, same);
        pos++;
        if (pos == pos_last){
            pos = 0;
            lin++;
        }
        find_pal(outfile, input, pos, lin);
}
}

int main()
{
    bool con = true;
    while (con == true)
    {
        string input;
        ifstream infile;
        infile.open ("file_read.txt");    
        getline(infile,input); // Saves the lines from the file in string input.
        infile.close();

        transform(input.begin(), input.end(), input.begin(), ::tolower); // Goes to all Lower Case

        string inputer = remover(input); // Removes unwanted symbols, numbers, spaces, etc
        input = inputer; // Updates our orignal string input

        ofstream outfile ("file_out.txt");
        int pos = 0;
        int lin = 3;
        find_pal(outfile, input, pos, lin); // Start the palindron function up to sift       through purmutations

        string full_input = string_reverse(input); // Final Purmutation of reverse
        bool same = equals(input, full_input);
        process_pal(outfile, input, full_input, same); // Final analyzing process_pal

        string go;
        outfile.close();    
        cout << "Continue? y/n " << endl; // Continue on or not
        getline(cin, go);
        if(go != "y")
            con = false;
    }
    system("pause");
    return 0;
}

最佳答案

在C/C++中有栈和堆。堆栈通常是固定大小的内存段,可能比您想象的要小(默认值可能约为 1-2MB),而堆是内存的动态部分,它会一直增长,直到您超过了内存上的总逻辑 RAM服务器。

对您的问题的简短回答是,每次嵌套函数调用时,您都会在所谓的“堆栈框架”中分配更多的内存。所以如果你有“主调用 A 调用 B 再次调用 B”那么你有 4 个堆栈帧。如果你有一个随着输入大小而增长的递归方法,那么你将开始分配大量堆栈帧,最终你将出现堆栈溢出异常(堆栈的大小已超过固定限制)。

所以,一般来说,你的问题的根本原因是你的递归嵌套太深了。有几种方法可以解决这个问题。评论中提到的一种常见方法是简单地放弃递归。另一种方法是使用 tail recursion这避免了在每次调用时添加新的堆栈帧,并允许您保留递归语义。

综上所述,我应该提一下,如果您要切换到指针,您可能会看到一个的好处。这是因为堆栈帧的大小取决于函数参数和局部变量的大小。指针可能比您传入的某些其他结构小,并可能导致更小的堆栈帧。但是,这不是问题的根本原因。

关于c++ - 这个 StackOverFlowException 是否需要指针才能正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16073450/

相关文章:

visual-c++ - VS2015 UCRT源文件在哪里?

c++ - 当我们在CUDA中调用内核时,是否发生上下文切换?

c++ - 引用基类的 constexpr 构造函数因编译器而异

c++ - 在不知道派生类的情况下从父类调用派生类函数

c++ - 从 .begin() 和 .end() 迭代器获取数组

c++ - VC++ 注释、文档和 IntelliSense

c# - 在 c# 中构建一个整数数组,每个调用 c++ 或在 c++ 中构建并传递给 c#?

c++ - 使用 Visual C++ 和 MFC 发出 ping 声音错误

c++ - 将字符串标记存储到数组中

c++ - 在 Qt 中动态添加小部件时出现段错误