Cstring - debug断言失败;缓冲区太小

时间:2022-10-21 20:21:55

I have this piece of code which keeps throwing a 'buffer too small' error during debug.

我有这段代码,它在调试过程中不断抛出“缓冲区太小”的错误。

        geoGraph.size=limit;
        CString xAxis ="X axis: ",yAxis="Y axis: ";

        for (int x = 0; x < limit; x++)
        {

            xAxis.Format(_T("%s%i  "),xAxis,(x+1));
            yAxis.Format(_T("%s%s  "),yAxis,dialog_test.str[x]);

        }

        xAxis.Format(_T("%s \n%s  "),xAxis,yAxis);// <---Error thrown

        d.SetWindowTextA(xAxis);

I came into the conclusion that the error was due to the fact that the Cstring xAxis is too small to contain the new text, am I correct and if so, how do I remedy it?

我得出的结论是,错误是由于Cstring xAxis太小而无法包含新文本,我是否正确,如果是这样,我该如何补救?


Thanks.

谢谢。

Edit: I'm curios as to why this error is only shown during debugging and not when I'm running the application with 'start without debugging' (I use VS2008).

编辑:我很好奇为什么这个错误只在调试过程中显示,而不是在运行应用程序时,“启动而不调试”(我使用VS2008)。

4 个解决方案

#1


7  

No! The real problem was:

不!真正的问题是:

  1. xAxis Format starts and sees that there is need for more room. Based on the calculation of all the parameters given to Format.
  2. xAxis格式开始,并看到需要更多的空间。基于对所有参数的计算。
  3. Now xAxis storage is reallocated. The old pointer gets invalid and in the debug Version frees and overwrites it. So there is no 0 terminator any more. The memory is filled with a standard value for free Memory.
  4. 现在,xAxis存储被重新分配。旧指针无效,在调试版本中释放并覆盖它。所以不再有0终结者了。内存中有一个用于空闲内存的标准值。
  5. Format starts and collects from the old pointer (The Contents where it Points to just changed) and copies garbage and finds no 0 terminator.
  6. 格式化开始并从旧指针(它指向刚刚改变的内容)中收集并复制垃圾并找到0终止符。

Never use a CString in Format as target AND source! This might work in the Release Version, because the Memory MIGHT not be changed, but if it is changed the behaviour is undefined. But it is a real bad coding bug.

永远不要在格式上使用CString作为目标和来源!这可能在发布版本中起作用,因为内存可能不会被更改,但是如果更改了,则行为是未定义的。但是这是一个非常糟糕的编码错误。

#2


2  

The documentation for CStringT::Format contains the following remark:

CStringT的文档::格式包含以下备注:

The call will fail if the string object itself is offered as a parameter to Format. For example, the following code will cause unpredictable results:

如果字符串对象本身作为参数提供格式,则调用将失败。例如,以下代码将导致不可预测的结果:

CAtlString str = _T("Some Data");
str.Format(_T("%s%d"), str, 123);
// Attention: str is also used in the parameter list.

To work around this, you can either create a copy for the argument, or - in this specific case - call the CStringT::AppendFormat class member instead:

为了解决这个问题,您可以为这个参数创建一个副本,或者——在这个特定的情况下——调用CStringT::AppendFormat类成员:

geoGraph.size = limit;
CStringW xAxis = L"X axis: ",
         yAxis = L"Y axis: ";

for ( int x = 0; x < limit; ++x ) {
    xAxis.AppendFormat( L"%i  ", x + 1 );
    yAxis.AppendFormat( L"%s  ", dialog_test.str[x].GetString() );
}

xAxis.AppendFormat( L" \n%s  ", yAxis.GetString() );

Note in particular, that this implementation calls CSimpleStringT::GetString to retrieve a C-style string for use with the %s format specifier. Passing a CString object for a %s placeholder is not documented to work*.

特别要注意的是,这个实现调用CSimpleStringT::GetString,以检索使用%s格式说明符的c样式字符串。传递一个%s占位符的CString对象没有被记录到工作*。

Also observe, that this implementation uses explicit wide character versions of CString objects, as well as wide character string literals. All supported versions of Windows use Unicode (UTF-16) as their native encoding. Using Unicode in applications is thus a natural choice.

还可以观察到,这个实现使用了显式的CString对象的字符版本,以及宽字符字符串的文本。所有支持的Windows版本都使用Unicode (UTF-16)作为它们的本地编码。因此,在应用程序中使用Unicode是一种自然选择。


*All currently supported versions of ATL/MFC implement CString in a way that allows to pass a CString object anywhere a C-style character string is expected. This also works for variable argument lists. The latter is an implementation detail, and not part of the documented contract. It should not be relied upon.

#3


1  

If your objective is to reuse the variables, you can do:

如果您的目标是重用这些变量,您可以这样做:

    geoGraph.size=limit;
    CString xAxis ="X axis: ",yAxis="Y axis: ";

    for (int x = 0; x < limit; x++)
    {

        xAxis.Format(_T("%s%i  "), CString(xAxis),(x+1));
        yAxis.Format(_T("%s%s  "), Cstring(yAxis),dialog_test.str[x]);

    }

    xAxis.Format(_T("%s \n%s  "), CString(xAxis),yAxis);

    d.SetWindowTextA(xAxis);

I had a similar situation and it worked, because I am now using a copy of the xAxis variable instead of it directly.

我有一个类似的情况,它起作用了,因为我现在使用的是xAxis变量的副本,而不是直接使用它。

#4


-1  

Problem solved. Used;

问题解决了。使用;

xAxis.AppendFormat(_T("\n%s  "),yAxis);

#1


7  

No! The real problem was:

不!真正的问题是:

  1. xAxis Format starts and sees that there is need for more room. Based on the calculation of all the parameters given to Format.
  2. xAxis格式开始,并看到需要更多的空间。基于对所有参数的计算。
  3. Now xAxis storage is reallocated. The old pointer gets invalid and in the debug Version frees and overwrites it. So there is no 0 terminator any more. The memory is filled with a standard value for free Memory.
  4. 现在,xAxis存储被重新分配。旧指针无效,在调试版本中释放并覆盖它。所以不再有0终结者了。内存中有一个用于空闲内存的标准值。
  5. Format starts and collects from the old pointer (The Contents where it Points to just changed) and copies garbage and finds no 0 terminator.
  6. 格式化开始并从旧指针(它指向刚刚改变的内容)中收集并复制垃圾并找到0终止符。

Never use a CString in Format as target AND source! This might work in the Release Version, because the Memory MIGHT not be changed, but if it is changed the behaviour is undefined. But it is a real bad coding bug.

永远不要在格式上使用CString作为目标和来源!这可能在发布版本中起作用,因为内存可能不会被更改,但是如果更改了,则行为是未定义的。但是这是一个非常糟糕的编码错误。

#2


2  

The documentation for CStringT::Format contains the following remark:

CStringT的文档::格式包含以下备注:

The call will fail if the string object itself is offered as a parameter to Format. For example, the following code will cause unpredictable results:

如果字符串对象本身作为参数提供格式,则调用将失败。例如,以下代码将导致不可预测的结果:

CAtlString str = _T("Some Data");
str.Format(_T("%s%d"), str, 123);
// Attention: str is also used in the parameter list.

To work around this, you can either create a copy for the argument, or - in this specific case - call the CStringT::AppendFormat class member instead:

为了解决这个问题,您可以为这个参数创建一个副本,或者——在这个特定的情况下——调用CStringT::AppendFormat类成员:

geoGraph.size = limit;
CStringW xAxis = L"X axis: ",
         yAxis = L"Y axis: ";

for ( int x = 0; x < limit; ++x ) {
    xAxis.AppendFormat( L"%i  ", x + 1 );
    yAxis.AppendFormat( L"%s  ", dialog_test.str[x].GetString() );
}

xAxis.AppendFormat( L" \n%s  ", yAxis.GetString() );

Note in particular, that this implementation calls CSimpleStringT::GetString to retrieve a C-style string for use with the %s format specifier. Passing a CString object for a %s placeholder is not documented to work*.

特别要注意的是,这个实现调用CSimpleStringT::GetString,以检索使用%s格式说明符的c样式字符串。传递一个%s占位符的CString对象没有被记录到工作*。

Also observe, that this implementation uses explicit wide character versions of CString objects, as well as wide character string literals. All supported versions of Windows use Unicode (UTF-16) as their native encoding. Using Unicode in applications is thus a natural choice.

还可以观察到,这个实现使用了显式的CString对象的字符版本,以及宽字符字符串的文本。所有支持的Windows版本都使用Unicode (UTF-16)作为它们的本地编码。因此,在应用程序中使用Unicode是一种自然选择。


*All currently supported versions of ATL/MFC implement CString in a way that allows to pass a CString object anywhere a C-style character string is expected. This also works for variable argument lists. The latter is an implementation detail, and not part of the documented contract. It should not be relied upon.

#3


1  

If your objective is to reuse the variables, you can do:

如果您的目标是重用这些变量,您可以这样做:

    geoGraph.size=limit;
    CString xAxis ="X axis: ",yAxis="Y axis: ";

    for (int x = 0; x < limit; x++)
    {

        xAxis.Format(_T("%s%i  "), CString(xAxis),(x+1));
        yAxis.Format(_T("%s%s  "), Cstring(yAxis),dialog_test.str[x]);

    }

    xAxis.Format(_T("%s \n%s  "), CString(xAxis),yAxis);

    d.SetWindowTextA(xAxis);

I had a similar situation and it worked, because I am now using a copy of the xAxis variable instead of it directly.

我有一个类似的情况,它起作用了,因为我现在使用的是xAxis变量的副本,而不是直接使用它。

#4


-1  

Problem solved. Used;

问题解决了。使用;

xAxis.AppendFormat(_T("\n%s  "),yAxis);