这是一个相当新手的问题,应该能够合理地迅速回答......
基本上,在 echo 中第一次调用 Printf 之后, args 的内容已损坏。听起来像我正在错误地传递指针。但无法弄清楚为什么?
#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,如果不清楚的话......
编辑这是在vs2008
更新 对于任何感兴趣的人来说,问题似乎是一个溢出的调用堆栈,在堆栈的下方,然后定义了另一个大型数组。重构这可以消除内存损坏。所以用粉笔来筹码!
答案 0 :(得分:3)
您尚未提及此代码运行的环境。可能是你在吹嘘。您在RiseWindows :: Print中声明堆栈上的32767字节数组。在我熟悉的某些嵌入式系统环境中,这将是个坏消息。你可以增加堆栈大小和/或在堆上分配缓冲区来测试该理论吗?您可能希望将该缓冲区改为std :: vector,或者可能是私有成员向量,以避免每次调用Print时分配和重新分配它。
沿着这些方向,MAX_PRINT_OUTPUT有多大?
答案 1 :(得分:2)
可能不是你要问的bug,但是在你的循环中,你在某些情况下是双重递增pBuffer,这可能会推动你超过缓冲区的末尾,因为你只检查长度为1(对于空终止)。
答案 2 :(得分:2)
你有没有尝试过分而治之的策略?
在单独的窗口中观察args []指向的内存,而您一步一步也可以提供帮助。
答案 3 :(得分:2)
随机猜测:我觉得问题是由Printf中的这一行引起的:
char formattedOutput[MAX_PRINT_OUTPUT];
我认为这是因为你有一些明显声明的指针和一些明显未申报的指针。一个字符数组是一个指针 - 没有办法解决这个问题,但这并不明显。在Echo的函数定义中,args被定义为TWO DIMENSIONAL ARRAY,因为你将它作为
*args[MAX_COMMAND_ARGS]
你想要吗?我的猜测是无意中将某些内容作为引用而不是值传递,因为什么是指针与数组的模糊定义,并且您将指针传递给指针,该指针是数组的开头,而不是指针。数组的开头。因为当你进入RiseWindows :: Print时你说它被破坏了我的猜测是你传递了错误的东西。
另外,指向char的const指针只保留指针的值,据我所知,而不是指针内容的值。
答案 4 :(得分:1)
我是否可以建议逐步使用调试器来查看代码损坏的位置?
答案 5 :(得分:1)
while(pOutput [i]&amp;&amp;((pBuffer - buffer)&lt; sizeof(buffer) - 1))
更改为:
while(pOutput [i]&amp;&amp;((pBuffer - buffer)&lt; sizeof(buffer) - 2))
您一次只能写2个字符,因此您需要确保有两个字符的空间。
答案 6 :(得分:0)
不确定它是否应该如何工作但是Echo没有打印出args的第一个元素
// Changed i=1 to i=0;
for (int i = 0; i < argCount; ++i)
{
Printf("%s ", args[i]);
Printf("\n");
}
答案 7 :(得分:0)
您希望将#define从函数调用中移出到文件顶部:
在这种情况下,这可能不会导致腐败,但这是非标准的,很容易引起问题。
答案 8 :(得分:0)
工作理论是我们用以下方式吹嘘:
char buffer [CONSOLE_OUTPUT_SIZE]; char * pBuffer = buffer;
而是尝试:
char * pBuffer = new char [CONSOLE_OUTPUT_SIZE];
然后记得最后调用delete [] pBuffer。
答案 9 :(得分:0)
我还没有真正研究过这个问题,但是你的类型已经混淆了......这非常迂腐,但它确实对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中。)