在c++中保留分配的内存的问题,信号11

问题描述 投票:0回答:1

这是我为带有在线检查系统的作业编写的代码。 适用于给定的示例和我自己的简短示例,但检查系统表示它运行不正确并由于信号 11 而结束。

#include <iostream>
#include <string>
using namespace std;

int main()

{
    string mn;
    string x;
    char y;

    for(int i = 0; i < 2000; i++)
    {
        cin >> x;
        if(x!="DELETE")
        {
            cin >> y;
            
            if(x == "APPEND")
            {
                mn = mn + y;
            }
            
            else if(x == "CHANGE")
            {
                mn.pop_back();
                mn = mn + y;
            }

            else if(x == "PUSH")
            {
                int p = mn.find(y);
                if(mn[p] == 'Z')
                {mn[p] = 'A';}
                else
                {mn[p] = char(int(mn[p]) + 1);}
            }
        }
        else
        {
            int u;
            cin >> u;
            mn.pop_back();
        }
    }
    cout << mn;
}

我试图尽快修复它,因为我不知道我怎么可能留下分配的内存。谢谢!

通过用循环替换 a.find() 来修复它,基本上以某种方式做同样的事情,但我仍然不明白为什么这个版本不起作用。

c++
1个回答
0
投票

通过用循环替换 a.find() 来修复它,基本上以某种方式做同样的事情,但我仍然不明白为什么这个版本不起作用。

如果您发布了为您提供工作版本的循环替换,我可以解释为什么循环有效以及它与 string::find 操作有何不同。

每当使用可能导致边缘情况的函数时,您应该通过处理它们来保护您的代码,以避免错误或未定义的行为。

std::string::find
参考(https://en.cppreference.com/w/cpp/string/basic_string/find)说:
for a non-empty substring, if pos >= size(), the function always returns npos.

并给出了如何识别此问题的示例:
if (std::string::npos == n)

npos
参考(https://en.cppreference.com/w/cpp/string/basic_string/npos)说:

static const size_type npos = -1;
This is a special value equal to the maximum value representable by the type size_type.  
The exact meaning depends on context, but it is generally used either as end of string  
indicator by the functions that expect a string index or as the error  
indicator by the functions that return a string index.

std::string::pop_back
参考(https://en.cppreference.com/w/cpp/string/basic_string/pop_back)说:
The behavior is undefined if the string is empty.

即使您没有深入查看这些参考资料,您仍然可以尝试查找边缘情况并放入打印跟踪代码(或只是在调试器中工作)以了解代码为何以意外方式运行。

参见 https://www.ideone.com/RlZ0ee
有关如何添加打印跟踪语句的示例。它显示标准输入:

APPEND
c
APPEND
e
PUSH
c
PUSH
Z
DELETE
1

和标准输出(显示程序在处理其余输入之前停止):

i:0  APPEND:c  mn: c
i:1  APPEND:e  mn: ce
i:2  PUSH:c
i:2  PUSH:c  mn: de
i:3  PUSH:Z
p == npos = -1  DANGER: ACCESSING MEMORY OUTSIDE OF STRING CHARS
i:3  PUSH:Z  mn: de9C@�O�PUSHD �+a��@�O�@k��`�����������O�z
a�@�y�����#�@�O��y�yH5ܞy����
�O��A-a�Y�+a��@�O��@�O�JO�QO�bO�vO��O��O��O��O��O�!O�3����d@@8�*a�    �@kNkN
����O��O���O�|1he�=�w~|)���<x86_64

此垃圾表明代码不再打印合法的 std::string。就像数组一样,我们通常不期望 array[-1] 是可以接受的;这同样适用于字符串。这是添加了跟踪语句的程序:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string mn;
    string x;
    char y;

    for(int i = 0; i < 5; i++)
    {
        cin >> x;
        if(x!="DELETE")
        {
            cin >> y;
            if(x == "APPEND")
            {
                mn = mn + y;
                cout << "i:"<< i << "  " << x << ":" << y << "  mn: " << mn << endl;
            }
            else if(x == "CHANGE")
            {
                mn.pop_back();
                mn = mn + y;
                cout << "i:"<< i << "  " << x << ":" << y << "  mn: " << mn << endl;
            }
            else if(x == "PUSH")
            {
                int p = mn.find(y);
                cout << "i:"<< i << "  " << x << ":" << y << endl;
                if( p == string::npos)
                {
                    cout << "p == npos = " << p << "  DANGER: ACCESSING MEMORY OUTSIDE OF STRING CHARS" << endl;
                }
                if(mn[p] == 'Z') {
                    mn[p] = 'A';
                }
                else {
                    mn[p] = char(int(mn[p]) + 1);
                }
                cout << "i:"<< i << "  " << x << ":" << y << "  mn: " << mn << endl;
            }
        }
        else
        {
            int u;
            cin >> u;
            mn.pop_back();
            cout << "i:"<< i << "  " << x << ":N/A" << "  mn: " << mn << endl;
        }
    }
    cout << mn;
}
© www.soinside.com 2019 - 2024. All rights reserved.