0

我有这个从串口读取数据的程序。对于每一行,我试图将当前时间与数据行连接起来。出于某种原因,它在第二次打印时崩溃(它似乎在括号的末尾?)。奇怪的是,如果我注释打印出来,它仍然会崩溃

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 字节块的内存地址。IE:

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

我强调这种区别的原因是下一行将其全部抹去:

cdata = convertBSTRToString(data);

该行将 cdata 设置为指向由 . 返回的任何内存地址convertBSTRToString。这行之前的值无关紧要cdata——未初始化、空、指向未命名的内存块——现在它指向由convertBSTRToString.

滥用更多的 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将获取第二个参数指向的数据,并将其逐字节复制到第一个参数指向的位置。它不注意缓冲区大小。这是一个非常愚蠢的副本。没有任何安全性 - 这取决于您提供。

我不确定你想用这条线完成什么,因为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,然后 strcpy convertBSTRToString,然后 strcat currentDateTime。strcpy 不会追加, strcat 会。

于 2013-08-21T23:14:06.520 回答