提示
Windows has triggered a breakpoint in RingBufTest.exe.
This may be due to a corruption of the heap, which indicates a bug in RingBufTest.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while RingBufTest.exe has focus.
The output window may have more diagnostic information.
部分代码如如下
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = new char[cnNewSize];
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memcpy(szNewBuf,m_szBuf,m_nBufSize);
SAFE_DELETE_ARRAY(m_szBuf);//~~~~~~~~~~~~~~~~~~~~~~~
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
}
return true;
}
首次经过 SAFE_DELETE_ARRAY(m_szBuf); 的时候没有问题 但是第二次经过的时候 就有上面的错误了 麻烦大家看看是咋会回事呢?
19 个解决方案
#1
SAFE_DELETE_ARRAY(m_szBuf);的代码呢?
#2
现有代码如下:
#ifndef CSRINGBUF_H_
#define CSRINGBUF_H_
#define RINGBUFSIZE 24
class CSRingBuf
{
public:
CSRingBuf();
//init
void Init(const int cnBufSize = RINGBUFSIZE);
//read from the ring buffer
void SetupRead(char* szReadBuf,const int cnBufLength);
//write to the ring buffer
void SetupWrite(const char* cszWriteBuf,const int cnBufLength);
//if the buffer is null
bool IsEmpty();
//if the buffer is full
bool IsFull();
//resize ring buffer
bool Resize(const int cnNewSize);
//get pos of read
int GetReadPos();
//get pos of write
int GetwritePos();
virtual ~CSRingBuf();
private:
//pointer of read
int m_nReadPtr;
//pointer of write
int m_nWritePtr;
//buffer
char* m_szBuf;
//the buffer size alloactor
int m_nBufSize;
private:
//no implement
CSRingBuf (const CSRingBuf&);
CSRingBuf& operator = (const CSRingBuf&);
};
#endif
#include "CSRingBuf.h"
#ifndef _MACRO_H_
#include "Macro.h"
#endif
#include<stdio.h>
CSRingBuf::CSRingBuf()
{
Init();
}
void CSRingBuf::Init(const int cnBufSize)
{
m_nReadPtr = 0;
m_nWritePtr = 0;
m_nBufSize = cnBufSize;
m_szBuf = new char[m_nBufSize];
memset(m_szBuf,0,m_nBufSize);
}
void CSRingBuf::SetupRead(char* szReadBuf,const int cnBufLength)
{
if(IsEmpty())
{
return ;
}
//if m_nReadPtr int from of m_nWritePtr
if(m_nReadPtr + cnBufLength < m_nWritePtr)
{
memcpy(szReadBuf,m_szBuf + m_nReadPtr,cnBufLength);
m_nReadPtr = m_nReadPtr + cnBufLength;
}
else
{
int ndistance = m_nWritePtr - m_nReadPtr;
memcpy(szReadBuf,m_szBuf + m_nReadPtr,ndistance);
m_nReadPtr = m_nReadPtr + ndistance;
}
return ;
}
void CSRingBuf::SetupWrite(const char* cszWriteBuf,const int cnBufLength)
{
//if the write pointer reach the position of m_nBufSize - 1,means there is no buffer can write,
//turn to begin of ring buffer
if(IsFull())
{
//if there is enough place to write
if(m_nReadPtr > cnBufLength)
{
memcpy(m_szBuf,cszWriteBuf,cnBufLength);
m_nWritePtr = cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
//no enough place,alloactor more memory
else
{
if(Resize(m_nBufSize + cnBufLength))
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr += cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
}
}
//the buffer is enough to write
int nBufLeftSize = m_nBufSize - m_nWritePtr;
if(nBufLeftSize - cnBufLength >= 0)
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr = m_nWritePtr + cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return;
}
else
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
m_nWritePtr += nBufLeftSize;
int nWriteLeftSize = cnBufLength - nBufLeftSize;
//if the read pointer more than the left write size
if(nWriteLeftSize <= m_nReadPtr)
{
memcpy(m_szBuf,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = nBufLeftSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
else
{
//new extra memory,and copy the left write data to the momory
if(Resize(m_nBufSize + nWriteLeftSize))
{
memcpy(m_szBuf + m_nBufSize,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
}
}
}
return ;
}
inline bool CSRingBuf::IsEmpty()
{
if(0 == m_nWritePtr)
{
return true;
}
return false;
}
inline bool CSRingBuf::IsFull()
{
if(m_nWritePtr == m_nBufSize - 1)
{
return true;
}
return false;
}
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = new char[cnNewSize];
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memcpy(szNewBuf,m_szBuf,m_nBufSize);
SAFE_DELETE_ARRAY(m_szBuf);
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
}
return true;
}
int CSRingBuf::GetReadPos()
{
return m_nReadPtr;
}
int CSRingBuf::GetwritePos()
{
return m_nWritePtr;
}
CSRingBuf::~CSRingBuf()
{
if(m_szBuf)
{
SAFE_DELETE(m_szBuf);
}
}
#3
#define SAFE_DELETE(x) try{ if( (x) != NULL ) { delete (x); (x) = NULL; } } catch(...) { TRACE("SAFE_DELETE error\n"); }
#define SAFE_DELETE_ARRAY(x) try{ if( (x) != NULL ) { delete[] (x); (x) = NULL; } } catch(...) { TRACE("SAFE_DELETE_ARRAY error\n"); }
#4
从函数名字来推测,IsEmpty应该是判断当前缓冲区是否有数据的函数
而从代码里面看,Resize只有在IsEmpty为假时才会更新szBuf 这不合理吧
#5
加断点,每次都看看m_szBuf的值是否正常吧
#6
嗯 kingstarer说的对 IsEmpty判断条件不对 当读指针和写指针都为0 的时候才为空。
跟踪进去值显示都是正常的
谢谢先。
跟踪进去值显示都是正常的
谢谢先。

#7
看了一下你的代码 发现你在环行缓冲里面搬数据时用memcpy 这也是挺危险的
建议改用memmove
建议改用memmove
#8
上面是我看错了
代码修改如下:
另外,提醒一下,debug下打印缓冲区内容的方法是错误的,不应该用printf("%s")
而应该用循环打印每一个字符出来
代码修改如下:
void CSRingBuf::SetupWrite(const char* cszWriteBuf,const int cnBufLength)
{
printf("m_readptr = %d, m_writeptr = %d\n", m_nReadPtr, m_nWritePtr);
printf("m_szBuf = %p, m_nBufSize = %d\n", m_szBuf, m_nBufSize);
//if the write pointer reach the position of m_nBufSize - 1,means there is no buffer can write,
//turn to begin of ring buffer
if(IsFull())
{
//if there is enough place to write
if(m_nReadPtr > cnBufLength)
{
memcpy(m_szBuf,cszWriteBuf,cnBufLength);
m_nWritePtr = cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
//no enough place,alloactor more memory
else
{
if(Resize(m_nBufSize + cnBufLength))
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr += cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
}
}
//the buffer is enough to write
int nBufLeftSize = m_nBufSize - m_nWritePtr;
if(nBufLeftSize - cnBufLength >= 0)
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr = m_nWritePtr + cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return;
}
else
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
m_nWritePtr += nBufLeftSize;
int nWriteLeftSize = cnBufLength - nBufLeftSize;
//if the read pointer more than the left write size
if(nWriteLeftSize <= m_nReadPtr)
{
memcpy(m_szBuf,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = nBufLeftSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
else
{
//new extra memory,and copy the left write data to the momory
if(Resize(m_nBufSize + nWriteLeftSize))
{
//Resize会修改m_nBufSize!!!
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
}
}
}
return ;
}
另外,提醒一下,debug下打印缓冲区内容的方法是错误的,不应该用printf("%s")
而应该用循环打印每一个字符出来
#9
另外ReSize我觉得应该是这样实现比较合理
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = record_new_array<char>(cnNewSize);
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memcpy(szNewBuf,m_szBuf,m_nBufSize);
}
SAFE_DELETE_ARRAY(m_szBuf);
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
return true;
}
#10
可以断点调试看看,我没看明白
#11
再次谢谢 kingstarer的建议。
record_new_array 还没用过 也没查到相关的资料。不知如何使用?打印的方式是为了查看方便 就暂时没有改了 ^_^
完善了下功能,测试是基本没有问题了,贴下,如有问题,麻烦指点下。
record_new_array 还没用过 也没查到相关的资料。不知如何使用?打印的方式是为了查看方便 就暂时没有改了 ^_^
完善了下功能,测试是基本没有问题了,贴下,如有问题,麻烦指点下。
/********************************************************************
created: 15:5:2010 7:36
file base: CSRingBuf
file ext: h
author: Clean Sky
purpose: a base class to implememt a ring buffer
*********************************************************************/
#ifndef CSRINGBUF_H_
#define CSRINGBUF_H_
#define RINGBUFSIZE 24
class CSRingBuf
{
public:
CSRingBuf();
//init
void Init(const int cnBufSize = RINGBUFSIZE);
//read from the ring buffer
void SetupRead(char* szReadBuf,const int cnBufLength);
//write to the ring buffer
void SetupWrite(const char* cszWriteBuf,const int cnBufLength);
//if the buffer is null
bool IsEmpty();
//if the buffer is full
bool IsFull();
//resize ring buffer
bool Resize(const int cnNewSize);
//get pos of read
int GetReadPos();
//get pos of write
int GetwritePos();
virtual ~CSRingBuf();
private:
//pointer of read
int m_nReadPtr;
//pointer of write
int m_nWritePtr;
//buffer
char* m_szBuf;
//the buffer size alloactor
int m_nBufSize;
private:
//no implement
CSRingBuf (const CSRingBuf&);
CSRingBuf& operator = (const CSRingBuf&);
};
#endif
#include "CSRingBuf.h"
#ifndef _MACRO_H_
#include "Macro.h"
#endif
#include<stdio.h>
CSRingBuf::CSRingBuf()
{
Init();
}
void CSRingBuf::Init(const int cnBufSize)
{
m_nReadPtr = 0;
m_nWritePtr = 0;
m_nBufSize = cnBufSize;
m_szBuf = new char[m_nBufSize];
memset(m_szBuf,0,m_nBufSize);
}
void CSRingBuf::SetupRead(char* szReadBuf,const int cnBufLength)
{
if(IsEmpty())
{
return ;
}
//if there is enough data to read until to the the end of buffer,read it
//if read point is in front of write point
if(m_nWritePtr > m_nReadPtr)
{
int nDistance = m_nWritePtr - m_nReadPtr;
if(nDistance >= cnBufLength)
{
memmove(szReadBuf,m_szBuf + m_nReadPtr,cnBufLength);
m_nReadPtr = m_nReadPtr + cnBufLength;
return ;
}
//the data is not enough to be read ? the condition will happen?
else
{
}
}
//write point is in front of read point
else
{
int nReadLeft = cnBufLength - (m_nBufSize - m_nReadPtr - 1);
memmove(szReadBuf,m_szBuf + m_nReadPtr, m_nBufSize - m_nReadPtr - 1);
//some data have not read completely yet,then read it from the head of buffer
memmove(szReadBuf + m_nBufSize - m_nReadPtr - 1,m_szBuf,nReadLeft);
m_nReadPtr = nReadLeft;
}
return ;
}
void CSRingBuf::SetupWrite(const char* cszWriteBuf,const int cnBufLength)
{
//case 1: cycle buffer is full,write pointer reachs the end of buffer;
//according to the read pointer,if read pointer'position is more than the size of
//data to write,turn to the head of cycle buffer,else alloactor more momory.
if(IsFull())
{
//if there is enough buffer to write
if(m_nReadPtr > cnBufLength)
{
memmove(m_szBuf,cszWriteBuf,cnBufLength);
m_nWritePtr = cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
//no enough buffer,alloactor more memory
else
{
//write partial of data until the buffer is full
int nBufLeftSize = m_nBufSize - m_nWritePtr - 1;
if(0 != nBufLeftSize)
{
memmove(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
}
int nWriteLeftSize = cnBufLength - nBufLeftSize;
if(Resize(m_nBufSize + nWriteLeftSize))
{
memmove(m_szBuf + (m_nBufSize - nWriteLeftSize) - 1,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize - 1;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
}
}
//case 2:cycle buffer is not full,write pointer is less than size of buffer.
int nBufLeftSize = m_nBufSize - m_nWritePtr - 1;
//the buffer is enough to write
if(nBufLeftSize - cnBufLength >= 0)
{
memmove(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr = m_nWritePtr + cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return;
}
//there is not enough buffer to write
//if the left buffer 'size adds the read pointer is more than the size of data to write
else
{
//write a partial of data to the buffer next to the write pointer until the buffer is full
memmove(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
int nWriteLeftSize = cnBufLength - nBufLeftSize;
//if the read pointer more than the left size of write
if(nWriteLeftSize <= m_nReadPtr)
{
//write another data to the head of cycle buffer
memmove(m_szBuf,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = nWriteLeftSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
else
{
//allocator more memory,write the old and the new data to th buffer
if(Resize(m_nBufSize + nWriteLeftSize))
{
memmove(m_szBuf + (m_nBufSize - nWriteLeftSize)- 1,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize - 1;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
}
}
}
return ;
}
inline bool CSRingBuf::IsEmpty()
{
if(0 == m_nWritePtr && 0 == m_nReadPtr)
{
return true;
}
return false;
}
inline bool CSRingBuf::IsFull()
{
if(m_nWritePtr == (m_nBufSize - 1))
{
return true;
}
return false;
}
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = new char[cnNewSize];
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memmove(szNewBuf,m_szBuf,m_nBufSize);
}
SAFE_DELETE_ARRAY(m_szBuf);
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
return true;
}
int CSRingBuf::GetReadPos()
{
return m_nReadPtr;
}
int CSRingBuf::GetwritePos()
{
return m_nWritePtr;
}
CSRingBuf::~CSRingBuf()
{
if(m_szBuf)
{
SAFE_DELETE_ARRAY(m_szBuf);
}
}
#12
改的差不多了,就不说啥了,为什么要用环形缓冲区呢?没见你从缓冲区中取东西,也就是类似队列的,队列有用环形缓冲区的。我还以为你自己实现了内存分配器呢。
#13
那个没啥用,只是我用来打印每次分配出来地址的
#14
个人觉得write那部分的if(m_nReadPtr > cnBufLength)//这里是否应该是m_nWritePtr+cnBufLength>cnBufLength呢?
#15
很少码如此多的代码,学习参观之,有点晕,还没有使用过这个功能~
#16
boost::circular_buffer
#17
友情up!~
#18
呵呵 这个我想是用来处理 网络中TCP的粘包问题的,初始化的时候分配一块足够大的内存,不断的往里面读和写,应该也不会太频繁的申请分配内存, 也用过链表实现的内存池,也带有分配器,就是想了解实现下。
#19
ok 问题解决 结贴。
#20
#1
SAFE_DELETE_ARRAY(m_szBuf);的代码呢?
#2
现有代码如下:
#ifndef CSRINGBUF_H_
#define CSRINGBUF_H_
#define RINGBUFSIZE 24
class CSRingBuf
{
public:
CSRingBuf();
//init
void Init(const int cnBufSize = RINGBUFSIZE);
//read from the ring buffer
void SetupRead(char* szReadBuf,const int cnBufLength);
//write to the ring buffer
void SetupWrite(const char* cszWriteBuf,const int cnBufLength);
//if the buffer is null
bool IsEmpty();
//if the buffer is full
bool IsFull();
//resize ring buffer
bool Resize(const int cnNewSize);
//get pos of read
int GetReadPos();
//get pos of write
int GetwritePos();
virtual ~CSRingBuf();
private:
//pointer of read
int m_nReadPtr;
//pointer of write
int m_nWritePtr;
//buffer
char* m_szBuf;
//the buffer size alloactor
int m_nBufSize;
private:
//no implement
CSRingBuf (const CSRingBuf&);
CSRingBuf& operator = (const CSRingBuf&);
};
#endif
#include "CSRingBuf.h"
#ifndef _MACRO_H_
#include "Macro.h"
#endif
#include<stdio.h>
CSRingBuf::CSRingBuf()
{
Init();
}
void CSRingBuf::Init(const int cnBufSize)
{
m_nReadPtr = 0;
m_nWritePtr = 0;
m_nBufSize = cnBufSize;
m_szBuf = new char[m_nBufSize];
memset(m_szBuf,0,m_nBufSize);
}
void CSRingBuf::SetupRead(char* szReadBuf,const int cnBufLength)
{
if(IsEmpty())
{
return ;
}
//if m_nReadPtr int from of m_nWritePtr
if(m_nReadPtr + cnBufLength < m_nWritePtr)
{
memcpy(szReadBuf,m_szBuf + m_nReadPtr,cnBufLength);
m_nReadPtr = m_nReadPtr + cnBufLength;
}
else
{
int ndistance = m_nWritePtr - m_nReadPtr;
memcpy(szReadBuf,m_szBuf + m_nReadPtr,ndistance);
m_nReadPtr = m_nReadPtr + ndistance;
}
return ;
}
void CSRingBuf::SetupWrite(const char* cszWriteBuf,const int cnBufLength)
{
//if the write pointer reach the position of m_nBufSize - 1,means there is no buffer can write,
//turn to begin of ring buffer
if(IsFull())
{
//if there is enough place to write
if(m_nReadPtr > cnBufLength)
{
memcpy(m_szBuf,cszWriteBuf,cnBufLength);
m_nWritePtr = cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
//no enough place,alloactor more memory
else
{
if(Resize(m_nBufSize + cnBufLength))
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr += cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
}
}
//the buffer is enough to write
int nBufLeftSize = m_nBufSize - m_nWritePtr;
if(nBufLeftSize - cnBufLength >= 0)
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr = m_nWritePtr + cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return;
}
else
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
m_nWritePtr += nBufLeftSize;
int nWriteLeftSize = cnBufLength - nBufLeftSize;
//if the read pointer more than the left write size
if(nWriteLeftSize <= m_nReadPtr)
{
memcpy(m_szBuf,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = nBufLeftSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
else
{
//new extra memory,and copy the left write data to the momory
if(Resize(m_nBufSize + nWriteLeftSize))
{
memcpy(m_szBuf + m_nBufSize,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
}
}
}
return ;
}
inline bool CSRingBuf::IsEmpty()
{
if(0 == m_nWritePtr)
{
return true;
}
return false;
}
inline bool CSRingBuf::IsFull()
{
if(m_nWritePtr == m_nBufSize - 1)
{
return true;
}
return false;
}
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = new char[cnNewSize];
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memcpy(szNewBuf,m_szBuf,m_nBufSize);
SAFE_DELETE_ARRAY(m_szBuf);
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
}
return true;
}
int CSRingBuf::GetReadPos()
{
return m_nReadPtr;
}
int CSRingBuf::GetwritePos()
{
return m_nWritePtr;
}
CSRingBuf::~CSRingBuf()
{
if(m_szBuf)
{
SAFE_DELETE(m_szBuf);
}
}
#3
#define SAFE_DELETE(x) try{ if( (x) != NULL ) { delete (x); (x) = NULL; } } catch(...) { TRACE("SAFE_DELETE error\n"); }
#define SAFE_DELETE_ARRAY(x) try{ if( (x) != NULL ) { delete[] (x); (x) = NULL; } } catch(...) { TRACE("SAFE_DELETE_ARRAY error\n"); }
#4
从函数名字来推测,IsEmpty应该是判断当前缓冲区是否有数据的函数
而从代码里面看,Resize只有在IsEmpty为假时才会更新szBuf 这不合理吧
#5
加断点,每次都看看m_szBuf的值是否正常吧
#6
嗯 kingstarer说的对 IsEmpty判断条件不对 当读指针和写指针都为0 的时候才为空。
跟踪进去值显示都是正常的
谢谢先。
跟踪进去值显示都是正常的
谢谢先。

#7
看了一下你的代码 发现你在环行缓冲里面搬数据时用memcpy 这也是挺危险的
建议改用memmove
建议改用memmove
#8
上面是我看错了
代码修改如下:
另外,提醒一下,debug下打印缓冲区内容的方法是错误的,不应该用printf("%s")
而应该用循环打印每一个字符出来
代码修改如下:
void CSRingBuf::SetupWrite(const char* cszWriteBuf,const int cnBufLength)
{
printf("m_readptr = %d, m_writeptr = %d\n", m_nReadPtr, m_nWritePtr);
printf("m_szBuf = %p, m_nBufSize = %d\n", m_szBuf, m_nBufSize);
//if the write pointer reach the position of m_nBufSize - 1,means there is no buffer can write,
//turn to begin of ring buffer
if(IsFull())
{
//if there is enough place to write
if(m_nReadPtr > cnBufLength)
{
memcpy(m_szBuf,cszWriteBuf,cnBufLength);
m_nWritePtr = cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
//no enough place,alloactor more memory
else
{
if(Resize(m_nBufSize + cnBufLength))
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr += cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
}
}
//the buffer is enough to write
int nBufLeftSize = m_nBufSize - m_nWritePtr;
if(nBufLeftSize - cnBufLength >= 0)
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr = m_nWritePtr + cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return;
}
else
{
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
m_nWritePtr += nBufLeftSize;
int nWriteLeftSize = cnBufLength - nBufLeftSize;
//if the read pointer more than the left write size
if(nWriteLeftSize <= m_nReadPtr)
{
memcpy(m_szBuf,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = nBufLeftSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
else
{
//new extra memory,and copy the left write data to the momory
if(Resize(m_nBufSize + nWriteLeftSize))
{
//Resize会修改m_nBufSize!!!
memcpy(m_szBuf + m_nWritePtr,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
}
}
}
return ;
}
另外,提醒一下,debug下打印缓冲区内容的方法是错误的,不应该用printf("%s")
而应该用循环打印每一个字符出来
#9
另外ReSize我觉得应该是这样实现比较合理
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = record_new_array<char>(cnNewSize);
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memcpy(szNewBuf,m_szBuf,m_nBufSize);
}
SAFE_DELETE_ARRAY(m_szBuf);
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
return true;
}
#10
可以断点调试看看,我没看明白
#11
再次谢谢 kingstarer的建议。
record_new_array 还没用过 也没查到相关的资料。不知如何使用?打印的方式是为了查看方便 就暂时没有改了 ^_^
完善了下功能,测试是基本没有问题了,贴下,如有问题,麻烦指点下。
record_new_array 还没用过 也没查到相关的资料。不知如何使用?打印的方式是为了查看方便 就暂时没有改了 ^_^
完善了下功能,测试是基本没有问题了,贴下,如有问题,麻烦指点下。
/********************************************************************
created: 15:5:2010 7:36
file base: CSRingBuf
file ext: h
author: Clean Sky
purpose: a base class to implememt a ring buffer
*********************************************************************/
#ifndef CSRINGBUF_H_
#define CSRINGBUF_H_
#define RINGBUFSIZE 24
class CSRingBuf
{
public:
CSRingBuf();
//init
void Init(const int cnBufSize = RINGBUFSIZE);
//read from the ring buffer
void SetupRead(char* szReadBuf,const int cnBufLength);
//write to the ring buffer
void SetupWrite(const char* cszWriteBuf,const int cnBufLength);
//if the buffer is null
bool IsEmpty();
//if the buffer is full
bool IsFull();
//resize ring buffer
bool Resize(const int cnNewSize);
//get pos of read
int GetReadPos();
//get pos of write
int GetwritePos();
virtual ~CSRingBuf();
private:
//pointer of read
int m_nReadPtr;
//pointer of write
int m_nWritePtr;
//buffer
char* m_szBuf;
//the buffer size alloactor
int m_nBufSize;
private:
//no implement
CSRingBuf (const CSRingBuf&);
CSRingBuf& operator = (const CSRingBuf&);
};
#endif
#include "CSRingBuf.h"
#ifndef _MACRO_H_
#include "Macro.h"
#endif
#include<stdio.h>
CSRingBuf::CSRingBuf()
{
Init();
}
void CSRingBuf::Init(const int cnBufSize)
{
m_nReadPtr = 0;
m_nWritePtr = 0;
m_nBufSize = cnBufSize;
m_szBuf = new char[m_nBufSize];
memset(m_szBuf,0,m_nBufSize);
}
void CSRingBuf::SetupRead(char* szReadBuf,const int cnBufLength)
{
if(IsEmpty())
{
return ;
}
//if there is enough data to read until to the the end of buffer,read it
//if read point is in front of write point
if(m_nWritePtr > m_nReadPtr)
{
int nDistance = m_nWritePtr - m_nReadPtr;
if(nDistance >= cnBufLength)
{
memmove(szReadBuf,m_szBuf + m_nReadPtr,cnBufLength);
m_nReadPtr = m_nReadPtr + cnBufLength;
return ;
}
//the data is not enough to be read ? the condition will happen?
else
{
}
}
//write point is in front of read point
else
{
int nReadLeft = cnBufLength - (m_nBufSize - m_nReadPtr - 1);
memmove(szReadBuf,m_szBuf + m_nReadPtr, m_nBufSize - m_nReadPtr - 1);
//some data have not read completely yet,then read it from the head of buffer
memmove(szReadBuf + m_nBufSize - m_nReadPtr - 1,m_szBuf,nReadLeft);
m_nReadPtr = nReadLeft;
}
return ;
}
void CSRingBuf::SetupWrite(const char* cszWriteBuf,const int cnBufLength)
{
//case 1: cycle buffer is full,write pointer reachs the end of buffer;
//according to the read pointer,if read pointer'position is more than the size of
//data to write,turn to the head of cycle buffer,else alloactor more momory.
if(IsFull())
{
//if there is enough buffer to write
if(m_nReadPtr > cnBufLength)
{
memmove(m_szBuf,cszWriteBuf,cnBufLength);
m_nWritePtr = cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
//no enough buffer,alloactor more memory
else
{
//write partial of data until the buffer is full
int nBufLeftSize = m_nBufSize - m_nWritePtr - 1;
if(0 != nBufLeftSize)
{
memmove(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
}
int nWriteLeftSize = cnBufLength - nBufLeftSize;
if(Resize(m_nBufSize + nWriteLeftSize))
{
memmove(m_szBuf + (m_nBufSize - nWriteLeftSize) - 1,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize - 1;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
}
}
//case 2:cycle buffer is not full,write pointer is less than size of buffer.
int nBufLeftSize = m_nBufSize - m_nWritePtr - 1;
//the buffer is enough to write
if(nBufLeftSize - cnBufLength >= 0)
{
memmove(m_szBuf + m_nWritePtr,cszWriteBuf,cnBufLength);
m_nWritePtr = m_nWritePtr + cnBufLength;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return;
}
//there is not enough buffer to write
//if the left buffer 'size adds the read pointer is more than the size of data to write
else
{
//write a partial of data to the buffer next to the write pointer until the buffer is full
memmove(m_szBuf + m_nWritePtr,cszWriteBuf,nBufLeftSize);
int nWriteLeftSize = cnBufLength - nBufLeftSize;
//if the read pointer more than the left size of write
if(nWriteLeftSize <= m_nReadPtr)
{
//write another data to the head of cycle buffer
memmove(m_szBuf,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = nWriteLeftSize;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
return ;
}
else
{
//allocator more memory,write the old and the new data to th buffer
if(Resize(m_nBufSize + nWriteLeftSize))
{
memmove(m_szBuf + (m_nBufSize - nWriteLeftSize)- 1,cszWriteBuf + nBufLeftSize,nWriteLeftSize);
m_nWritePtr = m_nBufSize - 1;
#ifdef _DEBUG
printf("write data %s\n",m_szBuf);
#endif
}
}
}
return ;
}
inline bool CSRingBuf::IsEmpty()
{
if(0 == m_nWritePtr && 0 == m_nReadPtr)
{
return true;
}
return false;
}
inline bool CSRingBuf::IsFull()
{
if(m_nWritePtr == (m_nBufSize - 1))
{
return true;
}
return false;
}
bool CSRingBuf::Resize(const int cnNewSize)
{
if(cnNewSize < 0)
{
return false;
}
if(cnNewSize < m_nBufSize)
{
return false;
}
char* szNewBuf = new char[cnNewSize];
memset(szNewBuf,0,cnNewSize);
//if there is any data,copy to new buffer
if(!IsEmpty())
{
memmove(szNewBuf,m_szBuf,m_nBufSize);
}
SAFE_DELETE_ARRAY(m_szBuf);
m_szBuf = szNewBuf;
m_nBufSize = cnNewSize;
return true;
}
int CSRingBuf::GetReadPos()
{
return m_nReadPtr;
}
int CSRingBuf::GetwritePos()
{
return m_nWritePtr;
}
CSRingBuf::~CSRingBuf()
{
if(m_szBuf)
{
SAFE_DELETE_ARRAY(m_szBuf);
}
}
#12
改的差不多了,就不说啥了,为什么要用环形缓冲区呢?没见你从缓冲区中取东西,也就是类似队列的,队列有用环形缓冲区的。我还以为你自己实现了内存分配器呢。
#13
那个没啥用,只是我用来打印每次分配出来地址的
#14
个人觉得write那部分的if(m_nReadPtr > cnBufLength)//这里是否应该是m_nWritePtr+cnBufLength>cnBufLength呢?
#15
很少码如此多的代码,学习参观之,有点晕,还没有使用过这个功能~
#16
boost::circular_buffer
#17
友情up!~
#18
呵呵 这个我想是用来处理 网络中TCP的粘包问题的,初始化的时候分配一块足够大的内存,不断的往里面读和写,应该也不会太频繁的申请分配内存, 也用过链表实现的内存池,也带有分配器,就是想了解实现下。
#19
ok 问题解决 结贴。