0

シリアルポートからデータを読み取るこのプログラムがあります。行ごとに、現在の時刻とデータ行を連結しようとしています。何らかの理由で、2 番目の印刷のあたりでクラッシュします (括弧の終わりのように見えますか?)。奇妙な点は、印刷物にコメントを付けてもクラッシュすることです。

char * cdata;
{
    if( BINARY_ASCII == 1 ) //right now this is just set to 0, please ignore
    {
        cdata = convertBSTRToByteArray(data , numChars);
    }
    else
    {
        cdata = convertBSTRToString(data);

        //prints the original output
        cout << "before timestamp concat is: " << cdata << "\n";

        //this is supposed to concatenate each output line with the associated time
        std::stringstream ss;
        ss << currentDateTime() << "," << cdata;
        std::string s = ss.str();
        std::strcpy(cdata,s.c_str());

        cout << "after timestamp concat is: " << cdata << "\n"; //around here it crashes
}

cout << "after the thing" << "\n"; //does not even get here     

char * データが問題になると思っていましたが、次のように初期化してみました

char *cdata = 0;

char *cdata = new char [100];

変化なしに...

連結で何か間違ったことをしたと思いますか?

4

3 に答える 3

4

ここで、配列とポインターの違いを強調することが重要だと思います。

char * cdata;

これにより、 という名前のポインターが作成されcdataます。初期化されていないため、不要なメモリ アドレスが含まれています。ポインターは単なるメモリ アドレスです。つまり、32 (または 64) ビットを占有します。それだけです。

char *cdata = 0;

これにより、 という名前のポインターが作成されcdata、すべてゼロに初期化されます。これは、メモリ内の 0 番目の場所を指すことを意味します。これは通常、このポインタをたどってはいけないことを示すために使用されます。

char *cdata = new char [100];

これにより、100 文字のブロック (配列) が作成されますが、その配列には名前が付けられません。次に、という名前のポインターを作成しcdata、名前のない 100 バイト ブロックのメモリ アドレスに設定します。すなわち:

cdata [ 0x3Ad783B2 ] --------\
                              \
                               \
                               |
                               V
                             [ unnamed 100-byte block ]

私がこの区別を強調している理由は、次の行がそれをすべて消し去っているからです:

cdata = convertBSTRToString(data);

その行は、によって返されるメモリアドレスを指すように cdata を設定しますconvertBSTRToString。この行の前にどのような値があったか (初期化されていない、null、名前のないメモリ ブロックを指している) は関係ありません。現在は、によって作成されたメモリ ブロックを指していますcdataconvertBSTRToString

より多くの ASCII アートを悪用する:

cdata [ 0x64ADB7C8 ] --------\
                              \
                               \
                               |
                               V
                             [ unknown size, created by convertBSTRToString ]

                             // hey, look over here!  it still exists,
                             // but we just don't point to it anymore.
                             [ unnamed 100-byte block ]

それがカバーされたので、これが重要な理由です。この行:

std::strcpy(cdata,s.c_str());

strcpyは、2 番目のパラメーターが指すデータを取得し、最初のパラメーターが指す場所にバイト単位でコピーします。バッファサイズには注意を払いません。本当に馬鹿げたコピーです。安全性はまったくありません - それはあなた次第です。

s連結したい完全な文字列データを保持しているため、とにかくこの行で何を達成しようとしているのかわかりません。

cout << "after timestamp concat is: " << s << "\n";
于 2013-08-21T23:17:33.713 に答える
1

convertBSTRToStringおそらく、BSTR渡したものを保持するのに正確なサイズの新しいバッファーを割り当てます。つまり、そのサイズを拡張することはできません。

あなたのコードでは、currentDateTime()(既存のコンテンツに加えて) の結果をそのバッファに追加しようとしています。データが収まりません。したがって、悪いことが起こります。

于 2013-08-21T22:39:12.910 に答える
0

まず、convertBSTRToString と currentDateTime の両方を格納するのに十分な大きさのバッファを割り当ててから、convertBSTRToString を strcpy し、次に currentDateTime を strcat する必要があります。strcpy は追加しませんが、strcat は追加します。

于 2013-08-21T23:14:06.520 に答える