代码之家  ›  专栏  ›  技术社区  ›  Wookai

在不同位置删除指针会导致不同的行为(崩溃或不崩溃)

  •  1
  • Wookai  · 技术社区  · 16 年前

    这个问题是一个精化的问题 this one ,其方向与预期不同。

    在我的多线程应用程序中,主线程创建并存储参数:

    typedef struct {
        int parameter1;
        double parameter2;
        float* parameter3;
    } jobParams;
    
    typedef struct {
        int ID;
        void* params;
    } jobData;
    
    std::vector<jobData> jobs;
    
    // main thread
    for (int i = 0; i < nbJobs; ++i) {
        jobParams* p = new jobParams;
        // fill and store params
    
        jobData data;
        data.ID = i;
        data.params = p;
    
        jobs.push_back(data);
    }
    
    // start threads and wait for their execution
    
    // delete parameters
    for (int i = 0; i < jobs.size(); ++i) {
        delete jobs[i].params;
    }
    

    // thread (generic for any job function and any type of params)
    jobData* job = main->getNextParams();
    jobFunction(job->ID, job->params);
    

    void* jobFunction(void* param) {
        jobParams* params = (jobParams*) param;
        // do stuff
        return 0;
    }
    

    我的问题是:如果我 delete params 在…的结尾 jobFunction() jobFunction() 那是我写的。

    如果我试着 删除参数 刚打完电话 在踏板中,甚至在确保所有线程都已完成(因此不再需要参数)后的主线程中,我得到一个堆损坏错误:

    我使用的是Visual Studio 2008 Pro,因此无法使用valgrind或其他*nix工具进行调试。“子线程”对主线程的所有访问都是使用互斥锁同步的,因此问题不在于我删除了相同的参数两次。

    我添加了这两种结构的定义,以及删除参数的方式。

    3 回复  |  直到 4 年前
        1
  •  2
  •   Goz    16 年前

    正如我所想。。你能试试吗

    for (int i = 0; i < jobs.size(); ++i) {
        delete (jobParams*)jobs[i].params;
    }
    

    是否有任何理由将参数存储为jobData中的void*?我认为,如果您希望拥有不同类型的JobParam,那么您应该使用继承层次结构,而不是盲目地将其转换为空*。

        2
  •  1
  •   redtuna    16 年前

    这种错误通常意味着你在某个地方有一场数据竞赛。是否主要->getNextParams()即使同时被多个线程调用,也能做正确的事情吗?如果两个参数都相同,你就可以得到一个双自由度。

    而且,代替

    jobFunction(jobData->ID, jobData->params);
    

    jobFunction(job->ID, job->params);
    
        3
  •  1
  •   jon hanson    16 年前

    要调试它,您可以添加 deleted jobParams 类并将其设置为 true 而不是实际删除对象。然后查看并检查 删除 工作参数 如果是真的,则抛出异常。然后查看抛出异常的位置。