我有一个奇怪的问题,真的不明白发生了什么。
我使用 MFC 多线程类使我的应用程序多线程。
到目前为止一切正常,但现在:
在代码开头的某个地方,我创建了线程:
m_bucketCreator = new BucketCreator(128,128,32);
CEvent* updateEvent = new CEvent(FALSE, FALSE);
CWinThread** threads = new CWinThread*[numThreads];
for(int i=0; i<8; i++){
threads[i]=AfxBeginThread(&MyClass::threadfunction, updateEvent);
m_activeRenderThreads++;
}
这会创建 8 个线程来处理这个函数:
UINT MyClass::threadfunction( LPVOID params ) //executed in new Thread
{
Bucket* bucket=m_bucketCreator.getNextBucket();
...do something with bucket...
delete bucket;
}
m_bucketCreator
是静态成员。现在我在尝试删除缓冲区时在 Bucket 的解构函数中遇到了一些线程错误(但是,我理解它的方式应该是这个缓冲区应该在这个线程的内存中,所以我不明白为什么会出现错误)。在 delete[] buffer
的尝试中, 错误发生在 _CrtIsValidHeapPointer()
在 dbgheap.c
.Visual Studio 输出它捕获停止点的消息,这可能是由于堆损坏或因为用户按下 f12(我没有;))
class BucketCreator {
public:
BucketCreator();
~BucketCreator(void);
void init(int resX, int resY, int bucketSize);
Bucket* getNextBucket(){
Bucket* bucket=NULL;
//enter critical section
CSingleLock singleLock(&m_criticalSection);
singleLock.Lock();
int height = min(m_resolutionY-m_nextY,m_bucketSize);
int width = min(m_resolutionX-m_nextX,m_bucketSize);
bucket = new Bucket(width, height);
//leave critical section
singleLock.Unlock();
return bucket;
}
private:
int m_resolutionX;
int m_resolutionY;
int m_bucketSize;
int m_nextX;
int m_nextY;
//multithreading:
CCriticalSection m_criticalSection;
};
和类桶:
class Bucket : public CObject{
DECLARE_DYNAMIC(RenderBucket)
public:
Bucket(int a_resX, int a_resY){
resX = a_resX;
resY = a_resY;
buffer = new float[3 * resX * resY];
int buffersize = 3*resX * resY;
for (int i=0; i<buffersize; i++){
buffer[i] = 0;
}
}
~Bucket(void){
delete[] buffer;
buffer=NULL;
}
int getResX(){return resX;}
int getResY(){return resY;}
float* getBuffer(){return buffer;}
private:
int resX;
int resY;
float* buffer;
Bucket& operator = (const Bucket& other) { /*..*/}
Bucket(const Bucket& other) {/*..*/}
};
谁能告诉我这里可能是什么问题?
编辑:这是我从线程调用的另一个静态函数。这样做安全吗?
static std::vector<Vector3> generate_poisson(double width, double height, double min_dist, int k, std::vector<std::vector<Vector3> > existingPoints)
{
CSingleLock singleLock(&m_criticalSection);
singleLock.Lock();
std::vector<Vector3> samplePoints = std::vector<Vector3>();
...fill the vector...
singleLock.Unlock();
return samplePoints;
}
最佳答案
之前的所有回复都是正确的。对于复制构造函数,请确保它不只是复制缓冲区指针,否则会导致问题。它需要分配一个新缓冲区,而不是指针值,这会导致“删除”错误。但我不认为复制构造器会在您的代码中被调用。
我查看了代码,但没有看到任何错误。请注意,在这个 GetNextBucket 代码中甚至不需要线程同步,因为它返回一个局部变量并且这些是线程前的。
发生 ValidateHeapPointer 错误是因为某些东西损坏了堆,当指针写入内存块时会发生这种情况。通常是 for() 循环太过分了,缓冲区分配得不够大,等等。
在调用“delete”期间会报告该错误,因为那是在 Debug模式下验证堆是否存在错误的时候。但是,该错误发生在此之前,只是碰巧只在“新建”和“删除”中检查了堆。此外,它不一定与“桶”类有关。
如果没有使用 BoundsChecker 或 HeapValidator 之类的工具,您需要找到此错误,即注释掉您的代码部分,直到它消失,然后您会发现有问题的代码。
还有另一种方法可以缩小问题的范围。在 Debug模式下,包含在您的代码中,并在不同的兴趣点上调用 _CrtCheckMemory()。当堆损坏时,这将产生错误。只需移动代码中的调用以缩小损坏开始发生的时间点。
我不知道您使用的是哪个版本的 Visual C++。如果您使用的是早期版本,例如 VC++ 6.0,请确保您在编译器选项中使用的是 C 运行时库的 Multitreaded DLL 版本。
关于multithreading - MFC 多线程与 delete[] ,dbgheap.c,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1746159/