使用Char *抓取数据时出现队列,堆栈溢出错误 [英] Queue, Stack Overflow error when grabbing data using Char*

查看:81
本文介绍了使用Char *抓取数据时出现队列,堆栈溢出错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景:



有一个CString的队列,大小为30000.我逐个抓取数据。



代码:



<前lang =c ++> USES_CONVERSION

while (!DataQueue-> empty())
{
CString sTimeStamp = DataQueue-> front();
char * pChar = T2A(sTimeStamp);
// 使用pChar执行某些操作
DataQueue-> pop();
}





应用程序崩溃引发堆栈溢出错误。如果我删除了一段代码char * pChar = T2A(sTimeStamp);,则没有抛出错误,一切正常。我认为Char *行有内存泄漏或者内存没有被释放,并且在队列迭代完成之前导致堆内存的完全使用。



这就是我在while循环中尝试过的但没有任何效果,应用程序仍然崩溃:

  char  * pChar = sTimeStamp.GetBuffer( 0 ); 

char * pChar = T2A(sTimeStamp.GetBuffer( 0 ));

char * pChar
pChar = sTimeStamp.GetBuffer(sTimeStamp.GetLength());

char * pChar
strcpy(pChar,(LPCTSTR)sTimeStamp);

char * pChar1 = new [];
delete [] pChar;





我如何解决堆栈溢出错误?

解决方案

您显示的代码示例未显示问题。通常,这个问题很容易解决。



几乎100%的确定这是无限递归或相互递归的结果:

http://en.wikipedia.org/wiki/Recursion [ ^ ],

http://en.wikipedia.org/wiki/Mutual_recursion [ ^ ]。



使用调试器可以非常系统地解决这些问题。首先,您观察抛出异常的位置。在它发生之前设置一个断点并使用调试器窗口调用堆栈。您将看到来电的来源。找出无限递归的原因并设计退出递归的正确条件。通常,如果将调试与简单的逻辑相结合,可以非常快速地找到错误。



您对至少一个试图被调用的方法进行初步猜测无限次数。通常不需要很长时间才能找到这样的地方。你在这种方法的最开始处设置了断点,并尝试确认它发生了。当在断点上停止执行时,您可以向上或向下堆栈。下去更有效:你保持断点并逐步调试这个方法,首先做大步,直到你捕获相同的方法被更深层次的堆栈调用(记住你的断点仍在那里)。当它发生时,你重新开始并向前走一小步,直到找到递归的位置。这一次试图弄清楚为什么永远不会满足递归结束的条件。同时你将你的断点移近递归呼叫的来源,缩小你的网络。



听起来可能很难,但是很少练习总是给出100%的结果,不同于具有一些未知性质的不同错误的情况。如果堆栈溢出,您可以100%确定在开始查找之前可以找到问题。



-SA


T2A的文档告诉您它分配了用于存储堆栈中转换后的字符串的空间。是的,在退出函数之前不会返回此空格。如果你在循环中调用T2A,它将获得更多的堆栈,直到你最终达到堆栈溢出。这就是通常发生的事情。



解决方案:不要使用T2A,而是使用您自己分配并转换为该缓冲区的单个本地缓冲区。在循环的每次迭代中都可以使用相同的缓冲区。


来自nv3的解决方案2解释了什么是错误的。



无论如何,使用 CString 类,您可以使用 CStringA ,它支持使用赋值运算符从Unicode转换为ANSI:

  while (!DataQueue-> empty())
{
// 这假设DataQueue是一个CString列表
// 然后必须使用GetString()来获得LPCTSTR
CStringA sTimeStamp = DataQueue-> front()。GetString();
// 获取const ptr
// 如果要修改字符串,请使用GetBuffer()
const char * pChar = sTimeStamp.GetString();
DataQueue-> pop();
}


Scenario:

Have a queue of CString's with size 30000. I am grabbing the data one by one.

Code:

USES_CONVERSION

while (!DataQueue->empty())
{
	CString sTimeStamp = DataQueue->front();
	char* pChar = T2A(sTimeStamp);
	//do something with pChar
	DataQueue->pop();
}



The application is crashing throwing up a stack overflow error. If i remove the piece of code "char* pChar = T2A(sTimeStamp);", there is no error thrown and everything works fine. I think that the Char* line is having a memory leak or the memory is not freed and there by causing the complete usage of heap memory before the queue iteration completes.

This is all what i have tried with in the while loop but nothing worked, the application still crashes:

char* pChar = sTimeStamp.GetBuffer(0);

char* pChar = T2A(sTimeStamp.GetBuffer(0));

char* pChar
pChar = sTimeStamp.GetBuffer(sTimeStamp.GetLength());

char* pChar
strcpy(pChar, (LPCTSTR)sTimeStamp);

char*	pChar1 = new char[];
delete [] pChar;



How do i solve the stack overflow error?

解决方案

The code sample you show does not reveal the problem. Usually, this problem is easy enough to solve.

Almost 100% of certainty that this is result of "infinite" recursion or mutual recursion:
http://en.wikipedia.org/wiki/Recursion[^],
http://en.wikipedia.org/wiki/Mutual_recursion[^].

Such problems can be resolved in a very systematic way using the debugger. First, you observe where the exception is thrown. Put a break point before it happens and use the debugger window "Call stack". You will see where the calls come from. Find out the reason for infinite recursion and devise a correct condition of exit from recursion. Usually, the bug can be found very quickly if you combine debugging with simple logic.

You make an initial guess on at least one method which is attempted to get called "infinite" number of times. Usually it does not take long to find such place. You put break point(s) on a very beginning of such method(s) and try to confirm it happens. When the execution is stopped on a breakpoint, you can go up the stack or down the stack. It's more effective to go down: you keep the breakpoint and debug just one this method stepwise, making big steps at first, until you catch the same method being called deeper in stack (remember your breakpoint is still there). When it happens, you start over and go in smaller step until you pinpoint where the recursion goes. This time try to figure out why the condition of the recursion end is never met. At the same time you move your breakpoint(s) closer to the source of recursive call, narrowing your net.

It may sound difficult, but with little practice always gives 100% results, unlike the cases with different bugs of some unknown nature. In case of stack overflow, you can be 100% sure that you can find the problem before you start looking.

—SA


The documentation of T2A tells you that it allocates its space for storing the converted character string from the stack. Any yes, this space is not returned until you exit the function. If you call T2A in a loop it will grab more an more of the stack until you finally reach a stack overflow. And that is what typically happens.

Solution: Don't use T2A but a single local buffer that you allocate yourself and convert into that buffer. The same buffer can be used in each iteration of the loop.


Solution 2 from nv3 explains what is wrong.

When using the CString class anyway, you can use CStringA which supports conversion from Unicode to ANSI with the assignment operator:

while (!DataQueue->empty())
{
    // This assumes that DataQueue is a CString list
    // Then GetString() must be used to have a LPCTSTR
    CStringA sTimeStamp = DataQueue->front().GetString();
    // Get a const ptr
    // Use GetBuffer() instead if the string should be modified
    const char* pChar = sTimeStamp.GetString();
    DataQueue->pop();
}


这篇关于使用Char *抓取数据时出现队列,堆栈溢出错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆