字符串 - 调试断言失败;缓冲区太小

Cstring - debug assertion failed; buffer too small

本文关键字:缓冲区 失败 调试 断言 字符串      更新时间:2023-10-16

我有这段代码,它在调试期间不断抛出"缓冲区太小"错误。

        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);

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


谢谢。

编辑:我很好奇为什么此错误仅在调试期间显示,而不是在我以"启动而不调试"(我使用 VS2008(运行应用程序时显示。

不!真正的问题是:

  1. xAxis 格式启动并看到需要更多空间。基于给定格式的所有参数的计算。
  2. 现在,xAxis 存储已重新分配。旧指针无效,在调试版本中释放并覆盖它。所以不再有 0 终结者。内存填充了可用内存的标准值。
  3. 格式从旧指针(它指向的内容刚刚更改(开始并收集,并复制垃圾并找不到 0 终止符。

切勿使用格式中的 CString 作为目标和源!这可能在发行版本中有效,因为内存可能不会更改,但如果更改,则行为未定义。但这是一个真正糟糕的编码错误。

CStringT::Format 的文档包含以下备注:

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

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

若要解决此问题,可以为参数创建副本,或者 - 在此特定情况下 - 调用 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() );

特别要注意的是,此实现调用 CSimpleStringT::GetString 来检索 C 样式字符串以用于%s格式说明符。为%s占位符传递CString对象不会记录为有效*

另请注意,此实现使用 CString 对象的显式宽字符版本,以及宽字符串文本。所有受支持的 Windows 版本都使用 Unicode (UTF-16( 作为其本机编码。因此,在应用程序中使用 Unicode 是一个自然的选择。


*所有当前支持的 ATL/MFC 版本都以允许将 CString 对象传递到任何需要 C 样式字符串的地方的方式实现CString。这也适用于变量参数列表。后者是实施细节,而不是书面合同的一部分。不应依赖它。

如果您的目标是重用变量,则可以执行以下操作:

    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);

我遇到了类似的情况并且它有效,因为我现在使用 xAxis 变量的副本而不是直接使用它。

问题解决了。使用;

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