时间问题?程序在Visual Studio中运行良好,但不是独立的

时间:2014-11-19 16:49:51

标签: c# c++ visual-studio

我有一个原生的C ++ DLL。 DLL创建一个重复从外部设备读取数据的线程。如果数据读取速度不够快,设备可能会溢出。

'read'循环看起来像这样:

while (true)
{
    read_from_device();

    buffer_data();

    Sleep(5);  //Allow data to accumulate 
}

我还有一个使用上述DLL的C#应用​​程序。它调用DLL中的一个函数来启动“读取”线程,然后定期调用DLL中的另一个函数来检查是否已从外部设备读取所有数据。

应用程序和DLL都在Visual Studio中以“调试”模式构建(在本例中为2008)。

如果我通过Visual Studio运行应用程序,一切都很好:从外部设备读取数据,不会发生溢出。

当我运行相同的应用程序'standalone'(通过直接运行.exe)时,我遇到溢出。

我认为唯一的区别是,在第一个实例中,Visual Studio调试器会自动附加到应用程序?请记住,我没有设置断点。

我的应用程序中必须存在一个计时问题,当调试器连接到它时会以某种方式纠正吗?

我怎样才能调试此问题?

通过Visual Studio运行应用程序和直接运行应用程序之间还有什么区别?

编辑

以下是更详细的代码:

int buffer[MAX_EVENTS*2];
int bufferIndex = 0;
int eventsReturned = 0;

BufferObject *pNewBuffer;

while (bPollData)
{
    read_data(buffer[bufferIndex], &eventsReturned);

    bufferIndex += eventsReturned;

    if (bufferIndex >= MAX_EVENTS)
    {
        pNewBuffer = new BufferObject(buffer, bufferIndex);

        myList.AddTail(pNewBuffer);

        bufferIndex = 0;
    }

    Sleep(5);
}

...
... 

class BufferObject {
    int *buffer;
    int bufferSize;
public:
    BufferObject(int* source, int size)
    {
        buffer = new int[size];
        bufferSize = size;
        memcpy(buffer, source, size);
    }
};

2 个答案:

答案 0 :(得分:3)

   Sleep(5);

嗯,这就是你问题的99%。当您的代码快速运行时,您已经知道您遇到了问题。你人为地放慢速度来对这个bug施加创可贴。但是当你做一些 else 让你的代码运行得更快的时候,它当然不应该感到惊讶。就像没有附带调试器一样运行它。

你可能甚至不知道5是足够的事实。这是一个相当随机的数字,你的程序实际睡眠的时间很少是5毫秒。默认睡眠精度为15.625毫秒,但是当另一个程序调用timeBeginPeriod()时可能会改变。只需运行浏览器就足够了,Chrome臭名昭着地改变了中断率。因此,与15毫秒相比,你突然跑了3倍。打破你的计划。您不希望Chrome破坏您的计划;)

您必须解决真正的问题。这肯定就像你只需要花费设备发送给你的许多字节并将它放在BufferObject中。因此,如果您的程序运行速度很快,您将获得许多缓冲区对象,每个缓冲区对象都包含一些数据。这可能会对任何消耗数据的代码造成严重破坏。一个传统的问题是程序的用户界面紧张,疯狂地试图跟上所需的重绘。

如果没有足够深入的问题,随机猜测是你必须首先缓冲设备响应,直到它积累了足够的字节,以便将其粘贴在BufferObject中。如果你继续使用Sleep()创可贴,那么选择一个15.625的整数倍的睡眠量。像15,31,46。

答案 1 :(得分:2)

您可能正在收集数据的线程(以及构建缓冲区列表)与应用程序用来访问(并且可能删除)缓冲区的线程之间缺乏同步。

您可能需要在访问缓冲区列表时包含一些锁定。看来你有一个活跃的"只有数据读取器线程可以写入的缓冲区(缓冲区),当它已满时,将此数据复制到新的缓冲区对象中并将其添加到列表中。您可能会锁定列表的使用(列表可能包含内部正确的同步,但您的代码示例中不清楚)。

循环似乎无法通知read_data()函数它传入的缓冲区中的剩余空间,这可能是导致内存溢出的原因,可能会导致问题。

就个人而言,既然您无论如何都要动态分配缓冲区对象,我会完全跳过内存副本并简单地保存一个活动缓冲区对象并直接读入它,而不是放入临时缓冲区,然后将其复制到一个缓冲对象。

考虑到问题的性质和缺乏代码,我们不可能做更多的事情。