1

を繰り返し、その文字を使用して、認識された一連の文字の1つである場合const char *のインスタンスにオブジェクトを追加する関数があります。std::map

#define CHARSEQ const char*

void compile(CHARSEQ s) throw (BFCompilationError)
{
     std::cout << "@Receive call " << s << std::endl;

     for(int i = 0; s[i] != '\0'; i++)
     {
         if (std::string("<>-+.,[]").find_first_of(s[i]) == std::string::npos)
         {
             throw BFCompilationError("Unknown operator",*s,i);
         }
         std::cout << "@Compiling: " << s[i] << std::endl;
         std::cout << "@address s " << (void*)s << std::endl;
         std::cout << "@var s " << s << std::endl;
         controlstack.top().push_back(opmap[s[i]]);
     }
 }

渡される文字シーケンスは次のとおり"++++++++++." です。最初の3回の反復では、printステートメントは「+」、「+」、および「+」の期待値を表示し、の値はs引き続き「++++++++++」です。 +。」。ただし、4回目の反復で、がマングルされ、、、、、および他の多くの文字シーケンスなどのs奇妙な値が生成されます。例外をスローする行が削除され、ループの続行が許可されている場合、の値はその後変更されません。'Ð''öê''cR ''œk's

他の関数はアクセスできますsが、これはマルチスレッドプログラムではないため、なぜそれが重要になるのかわかりません。なぜ変更されるのかについてはそれほど混乱していませんsが、4回目の反復でのみ変更されるのはなぜですか。

私はSOを検索しましたが、関連性があると思われる投稿はこれだけですが、それでも私の質問には答えられません。(「constchar * change value」または同様の用語を検索すると、constの一部について何百もの投稿が表示されるため、調査は困難でした)。

最後に、私はおそらくを使用する必要があることを知ってstd::stringいます。答えが出ない場合は使用しますが、それでもこの動作を理解したいと思います。

編集:

この関数を呼び出すコードは次のとおりです。

CHARSEQ text = load(s);

std::cout << "@Receive load " << text << std::endl;

try
{
    compile(text);
}
catch(BFCompilationError& err)
{
    std::cerr << "\nError in bf code: caught BFCompilationError @" << err.getIndex() << " in file " << s << ":\n";
    std::cerr << text << '\n';
    for(int i = 0; i < err.getIndex(); i++)
    {
        std::cerr << " ";
    }
    std::cerr << "^\n";
    std::cerr << err.what() << err.getProblemChar() << std::endl;
    return 1;
}

どこloadにありますか:

CHARSEQ load(CHARSEQ fname)
{
    std::ifstream infile (fname);
    std::string data(""), line;
    if (infile.is_open())
    {
    while(infile.good())
    {
        std::getline(infile,line);
        std::cout << "@loading: "<< line << '\n';
        data += line;
    }
    infile.close();
}
else
{
    std::cerr << "Error: unable to open file: " << fname << std::endl;
}

return std::trim(data).c_str();

}

そして、ファイルfname++++++++++.1行に1文字になるように広げられます。

編集2:

コンソール出力の例を次に示します。

@loading: +
@loading: +
@loading: +
@loading: +
@loading: + 
@loading: +
@loading: +
@loading: +
@loading: +
@loading: +
@loading: .
@Receive load ++++++++++.
@Receive call ++++++++++.
@Compiling: +
@address s 0x7513e4
@var s ++++++++++.
@Compiling: +
@address s 0x7513e4
@var s ++++++++++.
@Compiling: +
@address s 0x7513e4
@var s ++++++++++.
@Compiling: 
@address s 0x7513e4
@var s ßu

Error in bf code: caught BFCompilationError @4 in file bf_src/Hello.txt:
ßu
^
Unknown operatorß
4

1 に答える 1

8

あなたのload機能に欠陥があります。によって返されるconst char*ポインタは、基になるオブジェクトが存在するc_str()までのみ有効です。std::stringただしdata、はのローカル変数でloadあり、戻り後にクリアされます。そのバッファはゼロで上書きされませんが、空きメモリとして残されます。したがって、戻った直後に値を出力することは機能する可能性がありますが、プログラムがそこに新しい値を配置する可能性があり、ポインターが指す値が変更されます。

std::string回避策として、loadの戻り値として使用することをお勧めします。

于 2013-01-17T22:57:00.053 に答える