首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用delete[]的MFC多线程

使用delete[]的MFC多线程
EN

Stack Overflow用户
提问于 2009-11-17 10:03:49
回答 2查看 1.6K关注 0票数 2

我有一个奇怪的问题,真的不明白发生了什么。

我使用MFC多线程类使我的应用程序成为多线程的。

到目前为止,一切运行正常,但现在:

在代码开头的某个地方,我创建了线程:

代码语言:javascript
复制
            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个线程处理此函数:

代码语言:javascript
复制
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时,错误发生在dbgheap.c中的_CrtIsValidHeapPointer()中。

Visual studio输出一条消息,指出它捕获了一个停止点,这可能是由于堆损坏或因为用户按下了f12 (我没有;)

代码语言:javascript
复制
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;
};

和类Bucket:

代码语言:javascript
复制
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) {/*..*/}
};

谁能告诉我这里可能出了什么问题?

edit:这是我从线程调用的另一个静态函数。这样做安全吗?

代码语言:javascript
复制
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;
     }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-17 12:07:29

之前的所有回复都是正确的。对于复制构造函数,请确保它不只是复制缓冲区指针,否则会导致问题。它需要分配一个新的缓冲区,而不是指针值,这将导致'delete‘中的错误。但我不认为在您的代码中会调用复制构造器。

我已经看过代码了,我看不出有任何错误。请注意,在这段GetNextBucket代码中,线程同步甚至不是必需的,因为它返回一个局部变量,而这些变量是预线程的。

ValidateHeapPointer中的错误发生是因为有东西破坏了堆,当指针写过一个内存块时就会发生这种情况。通常是for()循环走得太远,缓冲区分配得不够大,等等。

这个错误是在调用'delete‘时报告的,因为这是在调试模式下验证堆的bug的时候。然而,错误发生在此时间之前,只是碰巧堆只在'new‘和'delete’中被检查。而且,它不一定与“Bucket”类相关。

除了使用像BoundsChecker或HeapValidator这样的工具之外,你需要做的就是注释掉你的代码,直到它消失,然后你就会找到有问题的代码。

还有另一种方法可以缩小问题的范围。在调试模式下,将其包含在代码中,并在不同的兴趣点上分散对_CrtCheckMemory()的调用。这将在堆损坏时生成错误。只需移动代码中的调用,以缩小损坏开始发生的范围。

我不知道您使用的是哪个版本的Visual C++。如果您使用的是VC++ 6.0之类的早期版本,请确保在编译器选项中使用的是C运行时库的多线程DLL版本。

票数 2
EN

Stack Overflow用户

发布于 2009-11-17 11:20:05

您正在构建一个RenderBucket。你确定要从那里调用“Bucket”类的构造函数吗?它应该看起来像这样:

代码语言:javascript
复制
class RenderBucket : public Bucket {
  RenderBucket( int a_resX, int a_resY )
    : Bucket( a_resX, a_resY )
  {
  }
}

Bucket类中的Initializers将buffer设置为NULL是一个好主意...另外,将默认构造函数和复制构造函数设置为私有将有助于确保这些函数不会被使用。记住..。如果您不这样做,编译器将自动创建这些代码:

代码语言:javascript
复制
Bucket();  <-- default constructor
Bucket( int a_resx = 0, int a_resy = 0 )  <-- Another way to make your default constructor
Bucket(const class Bucket &B)  <-- copy constructor
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1746159

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档