这是一个相当新手的问题,应该很快就能回答......

基本上,在第一次调用之后 打印函数回声, ,内容 参数 已损坏。在我看来,我错误地传递了指针。但不明白为什么?

#define MAX_PRINT_OUTPUT 4096

void Echo(char *args[MAX_COMMAND_ARGUMENTS], int argCount)
{
    for (int i = 1; i < argCount; ++i)
    {
        Printf("%s ", args[i]);
        Printf("\n");
    }
};

void Printf(const char *output, ...)
{
    va_list args;
    char formattedOutput[MAX_PRINT_OUTPUT];

    va_start(args, output);
    vsnprintf(formattedOutput, sizeof(formattedOutput), output, args);
    va_end(args);

    g_PlatformDevice->Print(formattedOutput);
};

void RiseWindows::Print(const char *output)
{
    //Corruption appears to occur as soon as this function is entered
    #define CONSOLE_OUTPUT_SIZE 32767

    char buffer[CONSOLE_OUTPUT_SIZE];
    char *pBuffer = buffer;
    const char *pOutput = output;
    int i = 0;

    while (pOutput[i] && ((pBuffer - buffer) < sizeof(buffer) - 1))
    {
        if (pOutput[i] == '\n' && pOutput[i+1] == '\r' )
        {
            pBuffer[0] = '\r';
            pBuffer[1] = '\n';
            pBuffer += 2;
            ++i;
        }
        else if (pOutput[i] == '\r')
        {
            pBuffer[0] = '\r';
            pBuffer[1] = '\n';
            pBuffer += 2;
        }
        else if (pOutput[i] == '\n')
        {
            pBuffer[0] = '\r';
            pBuffer[1] = '\n';
            pBuffer += 2;
        }
        else
        {
            *pBuffer = pOutput[i];
            ++pBuffer;
        }
        ++i;
    }
    *pBuffer = 0;

    SendMessage(this->ConsoleWindow.hwndBuffer, EM_LINESCROLL, 0, 0xffff);
    SendMessage(this->ConsoleWindow.hwndBuffer, EM_SCROLLCARET, 0, 0);
    SendMessage(this->ConsoleWindow.hwndBuffer, EM_REPLACESEL, 0, (LPARAM)buffer);

};

笔记 这不是生产代码,只是概念证明。
编辑 g_PlatformDevice 的类型为 RiseWindows,如果不清楚的话...
编辑 这是在windows xp平台上运行的vs2008

更新对于任何感兴趣的人来说,问题似乎是溢出的调用堆栈,在堆栈的更下方,然后定义了另一个大数组。重构消除了内存损坏。所以用粉笔记下堆叠殴打!

有帮助吗?

解决方案

您尚未提及此代码运行的环境。可能是你在吹嘘。您在RiseWindows :: Print中声明堆栈上的32767字节数组。在我熟悉的某些嵌入式系统环境中,这将是个坏消息。你可以增加堆栈大小和/或在堆上分配缓冲区来测试该理论吗?您可能希望将该缓冲区改为std :: vector,或者可能是私有成员向量,以避免每次调用Print时分配和重新分配它。

沿着这些方向,MAX_PRINT_OUTPUT有多大?

其他提示

可能不是你要问的错误,但是在你的循环中,你在某些情况下是双重递增pBuffer,这可能会推动你超过缓冲区的末尾,因为你只检查长度为1(对于空终止)。

随机猜测:我觉得问题是由Printf中的这一行引起的:

char formattedOutput[MAX_PRINT_OUTPUT];

我认为这是因为你有一些明显声明的指针和一些明显未申报的指针。一个字符数组是一个指针 - 没有办法解决这个问题,但这并不明显。在Echo的函数定义中,args被定义为TWO DIMENSIONAL ARRAY,因为你将它作为

*args[MAX_COMMAND_ARGS]
你想要吗?我的猜测是无意中将某些内容作为引用而不是值传递,因为什么是指针与数组的模糊定义,并且您将指针传递给指针,该指针是数组的开头,而不是指针。数组的开头。因为当你进入RiseWindows :: Print时你说它被破坏了我的猜测是你传递了错误的东西。

另外,指向char的const指针只保留指针的值,据我所知,而不是指针内容的值。

您尝试过分而治之的策略吗?

  • 开始注释行直到它起作用。
  • 一旦它正常工作,请取消注释行,直到找到错误所在。

当您一步步执行时,在单独的窗口中观察 args[] 指向的内存也会有帮助。

我是否可以建议逐步使用调试器来查看代码损坏的位置?

while(pOutput [i] <!> amp; <!> amp;((pBuffer - buffer)<!> lt; sizeof(buffer) - 1))

更改为:

while(pOutput [i] <!> amp; <!> amp;((pBuffer - buffer)<!> lt; sizeof(buffer) - 2))

您一次只能写2个字符,因此您需要确保有两个字符的空间。

不确定它是否应该如何工作但是Echo没有打印出args的第一个元素

// Changed i=1 to i=0;
for (int i = 0; i < argCount; ++i)
{
    Printf("%s ", args[i]);
    Printf("\n");
}

您希望将#define从函数调用中移出到文件顶部:

预处理程序指令可以出现在源文件中的任何位置,但它们仅适用于源文件的其余部分。

在这种情况下,这可能不会导致腐败,但这是非标准的,很容易引起问题。

工作理论是我们用以下方式吹嘘:

char buffer [CONSOLE_OUTPUT_SIZE]; char * pBuffer = buffer;

而是尝试:

char * pBuffer = new char [CONSOLE_OUTPUT_SIZE];

然后记得最后调用delete [] pBuffer。

我还没有真正研究过这个问题,但是你的类型已经混淆了......这非常迂腐,但确实在C方面有所不同。

在这里,你有一个char数组。

char formattedOutput[MAX_PRINT_OUTPUT];

在这里,你有一个需要const char指针的函数。

void RiseWindows::Print(const char *output)

尝试:

void RiseWindows::Print(const char output[])

另外,我注意到你正在修改这些缓冲区中的内存 - 你确定可以这样做吗?至少,我确信你不能在不分配更多内存的情况下习惯性地使用更多内存。 (提示提示!)

我会分配自己的数组,并将字符串复制到其中。 然后,我将使用字符串函数替换适用的换行符。

最后,我强烈建议你在这里使用std :: string。 (虽然你无法将这些内容放入varargs中 - 你必须使用c-strings,但是当你可以的时候将它们复制回std :: string中。)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top