【问题标题】:Circular buffer writing randomly terminates the program?循环缓冲区写入随机终止程序?
【发布时间】:2013-08-13 17:25:51
【问题描述】:

“程序意外结束。”

我有一个班级正在调用CMem::Write()。并将迭代显示到屏幕上。有时会达到 140,其他... 12、3、42,立即掉出...非常随机。
如果我删除对CMem::Write() 的调用,程序将永远运行。

不知道为什么程序终止?我只能假设 CMem::Write() 方法中没有写一些东西。

CMem::CMem()//sets up the "static" stack memory and the pointers to it; also the "static" positionIndex
{
    m_nBufferLength = sizeof(char); //short int
    static char *cMessageCB = new char[m_nBufferLength];
    static double *dTimeCB = new double[m_nBufferLength];

    m_cMessageCB = cMessageCB;
    m_dTimeCB = dTimeCB;


    ////////////////////////////////////////
    static char *cMessageReadList = new char[m_nBufferLength]; //max size can be the CB
    static double *dTimeReadList = new double[m_nBufferLength]; //max size can be the CB

    m_cMessageReadList = cMessageReadList;
    m_dTimeReadList = dTimeReadList;

    static int firstInstance = 0;

    if(firstInstance == 0){
        m_posRead = 0;//only on first instance
        m_posWrite = 0;//only on first instance

        firstInstance++;//check to see if multiple threads entered at the same time and look at the count
    }
}


void CMem::Write()
{//double dTime, char cMessage
//only one thread can write at a time... so lock... (make other threads with various random delays)

    static bool bUse = false;
    bool bDone = false;


    while(bDone == false){

        if(bUse == false){
            bUse = true;


            m_cMessageCB[m_posWrite] = m_cMessageWrite;
            m_dTimeCB[m_posWrite] = m_dTimeWrite;

            m_posWrite = (unsigned char)(m_posWrite + 1);


            static char cFlag = 0;
            //if writing position == reading position then flag
            if(m_posWrite == m_posRead){
                cFlag = 1;
            }

            bDone = true;
            bUse = false;
        }else if(bUse == true){
            printf("SUSPEND ");
        }
    }
}


void CMem::Read()
{//get the whole block of memory and increment the m_posRead accordingly
    unsigned char j = 0;

    while( (m_posRead + 1) != (m_posWrite + 1) ){
        m_cMessageReadList[j] = m_cMessageCB[m_posRead];//inc m_posRead at the end
        m_dTimeReadList[j] = m_dTimeCB[m_posRead];//inc m_posRead at the end

        m_posRead = (unsigned char)(m_posRead + 1);//circulate around
        j++;// 'j' is not circulating back around
    }

    //write to file
}

【问题讨论】:

  • 通常情况下,如果您在调试器中运行编解码器,它将在程序“意外完成”时停止出现问题。
  • nobody 是否发布minimal complete examples
  • 你说这是一个循环队列,但是你什么时候回绕呢?我只看到在对 CMem::Write() 的调用中增加了写入位置。你应该这样做:if (m_posWrite == m_nBufferLength) m_posWrite = 0;
  • 您使用了很多静态变量。我建议改为将它们设为成员变量。在某些情况下,静态变量会导致问题。例如,这些值是否对所有类都通用?或者只是 CMem 的一个实例?如果是实例,那么它们不应该是静态的。
  • @Trenin,当你声明一个类型为 unsigned char 并且你的值是 255 时,当你将它增加 1 时会发生什么?它绕回 -1... 然后你转换它,因为操作是作为整数完成的,现在 -1 变成 0。

标签: c++ circular-buffer


【解决方案1】:

无论您提供什么代码,这似乎都是内存损坏的明显案例

第一

if(firstInstance == 0){
    m_posRead = 0;//only on first instance
    m_posWrite = 0;//only on first instance

    firstInstance++;//check to see if multiple threads entered at the same time and look at the count
}

以上代码仅在第一个实例中将 m_posRead 和 m_posWrite 初始化为 0。对于所有其他实例,它是未定义的。

其次,在你正在做的构造函数中

m_nBufferLength = sizeof(char); //short int
static char *cMessageCB = new char[m_nBufferLength];
m_cMessageCB = cMessageCB;

现在,这使得 m_cMessageCB 只有 1 个字节宽。同时,在 CMem::Write 你正在做的事情

m_cMessageCB[m_posWrite] = m_cMessageWrite;
m_dTimeCB[m_posWrite] = m_dTimeWrite;

m_posWrite = (unsigned char)(m_posWrite + 1);

此处 m_posWrite 已递增。第一次它将写入第 0 个索引。下次您调用 CMem:Write 时,它​​将尝试在第一个索引上写入,即“Array Out Of Bound Write”(因为 m_cMessageCB 只有 1 个字节宽)并且它的行为是未定义的。它可能会在下一次写入或任何其他未来写入时终止。

【讨论】:

    【解决方案2】:

    这些行似乎是这段代码的问题之一:

    if(firstInstance == 0){
    m_posRead = 0;//only on first instance
    m_posWrite = 0;//only on first instance
    

    为什么只在第一个实例上初始化索引?其他实例将使这些成员未初始化,因此显然它们会破坏内存。

    编辑(关于评论):

    好的,您可以将它们设为静态,但这表明您的设计存在严重问题。但这里是题外话。将它们设为静态后,另一个问题仍然存在:m_posWrite 变量只会递增,而不会重置/递减 - 您如何期望它不会超出范围?

    【讨论】:

    • 我也需要将它们设为静态...但问题仍未解决
    • 我已经编辑了答案并回复了您的评论。让我知道它是否仍然崩溃。
    • 问题是我有多个线程调用这些方法转储数据以跨套接字写入。我使用的是静态的,所以线程之间的事情保持一致。分配给非静态地址的成员变量将在每个线程中此类的每个实例化时有所不同。
    • '多线程','静态'。立即摆脱静态。
    • @Martin James,我需要在线程之间建立关系,静态是唯一可行的方法。如果您有任何想法,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    相关资源
    最近更新 更多