将堆上的变量发送到另一个线程

Posted

技术标签:

【中文标题】将堆上的变量发送到另一个线程【英文标题】:Send a variable on the heap to another thread 【发布时间】:2012-03-31 17:26:07 【问题描述】:

我在 C++ 中有一个奇怪的问题。布尔值的地址被“销毁”但没有被触及。我知道有更好的方法来完成我尝试做的事情,但我想知道我做错了什么。

我有一个主课;这个主类包含另一个类的向量。当创建此对象的新实例时,会出现一个奇怪的问题。

这就是我的代码的工作方式:

当调用“第二个”对象的构造函数时,将启动一个线程。该线程作为参数获取一个结构。这是结构:

struct KeyPressData

    vector<bool> *AutoPressStatus;
    vector<int> *AutoPressTime;
    bool * Destroy;
    bool * Ready;
;

结构体被构造函数填充:

MultiBoxClient::MultiBoxClient()

    //init data
    DestroyThread = new bool;
    ReadyThread = new bool;
    AutoThreadData = new KeyPressData;  

    //Reseting data
    *DestroyThread = false;
    *ReadyThread = false;   

    //KeyPressData configurating
    AutoThreadData->AutoPressStatus = &AutoPressStatus;
    AutoThreadData->AutoPressTime = &AutoPressTime;
    AutoThreadData->Destroy = DestroyThread;
    AutoThreadData->Ready = ReadyThread;

    //Start the keypress thread
    CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)AutoKeyThread,AutoThreadData,NULL,NULL); 

这是MultiBoxClient的定义:

class MultiBoxClient

    private:
        HWND ClientHandle;                                  
        vector<bool> KeyPresses;                                

        vector<bool> AutoPressStatus;                           
        vector<int> AutoPressTime;                              

        KeyPressData * AutoThreadData;                          

        bool * DestroyThread;                                       
        bool * ReadyThread;                                     

    public:
        MultiBoxClient();
        MultiBoxClient(HWND Handle);                            
        ~MultiBoxClient();                                      

        void EditClient(HWND Handle);                           

        void SendKeypress(vector<bool> KeyStatus);              
        void SendKeyCombination(unsigned int id);               
        void AutoCast(int Key,unsigned int Time,bool status);   

        bool IsAlive();                                         

;

MultiBoxClient 是这样创建的:

int main()

    MultiboxControler * MainControler = new MultiboxControler;

    while(true)
    
        Sleep(1000);
    

    delete MainControler;

    return false;

只要构造函数在运行,程序就可以正常运行。但是当构造函数关闭时,AutoThreadData-&gt;Destroy 的地址将被破坏。当我调用指针的值时程序会崩溃。

void WINAPI AutoKeyThread(void * ThreadData)


    KeyPressData * AutoThreadData = (KeyPressData*)ThreadData;

    while(true)
       
        if(*AutoThreadData->Destroy == true)    //CRASH
        
            *AutoThreadData->Ready = true;
            return;
        
        Sleep(100);
    

我测试了什么:

当构造函数运行和关闭时,我记录了 AutoThreadData 和 AutoThreadData-&gt;Destroy 的地址;当构造函数关闭时,AutoThreadData 地址等于AutoThreadData。所以这里没有问题。

AutoThreadData-&gt;Destroy 的地址在构造函数关闭时被销毁。但这怎么会发生呢?布尔值在堆上,KeyPressData 结构 (AutoThreadData) 在堆上。

Destroy before: 00A85328
Destroy after: FEEEFEEE

有人能解释一下为什么会崩溃吗?

我知道我可以将指向我的类的指针发送到线程。但我想知道这里出了什么问题。这样我就可以从错误中吸取教训。

有人可以帮我解决这个问题吗?

【问题讨论】:

能否在代码示例中添加MultiBoxClient的定义?另外,能不能把构造MultiBoxClient()的代码加进去? 谢谢,我添加定义和它的构造方式。 【参考方案1】:

我猜你对向量犯了一个错误,使用类指针,而不是类本身,像这样:

vector<class*> //instead of vector<class>

【讨论】:

你指的是什么类?我只看到boolint 的向量 他指出:“这个主类包含另一个类的向量。”这确实是我的问题。感谢每一位帮助我的人。 @user1201889 - 我看不出这个答案对你有什么帮助,因为在问题的代码中没有向量对象的访问(只获取向量的地址并分配它),所以很清楚,改变向量的类型不会有什么不同。因此,要么您没有发布代码的相关部分(比其他人如何猜测?),或者如果您这样做了,请告诉我您在问题代码中所做的更改,以使其根据此答案工作。 【参考方案2】:

0xFEEEFEEE 表示已释放内存。也就是说,您AutoThreadData 已被删除,并且它不在您处于无限循环中的工作线程上。所以,它必须是你的主线程,也可能是你没有显示的析构函数。

无论您在何处销毁/释放您的 KeyPressData 实例,请将其注释掉或在此处设置断点以找出它发生的位置。

【讨论】:

问题确实是在创建实例时调用了析构函数。但我没有调用它。我将主线程添加到帖子中。 @user1201889:基于堆栈的生命周期的全部意义在于,在作用域结束时会自动为您调用析构函数。 是的,但是当我在堆上创建对象时也会调用析构函数。 不要猜测 - 在析构函数中设置一个断点,一旦命中就检查调用堆栈,看看它是从哪里调用的。你不可能无缘无故地调用它。

以上是关于将堆上的变量发送到另一个线程的主要内容,如果未能解决你的问题,请参考以下文章

将变量从一个 PHP 页面发送到另一个

将数据发送到另一个 ViewController 的 Swift 问题

我们如何在 UI 线程中创建处理程序以将数据发送到另一个线程

将结构从一个进程发送到另一个进程的最简单方法是啥? [关闭]

将 iOS 设备上的触摸发送到另一个 UIScreen(外部显示器)

在php中将最后一个id插入变量发送到另一个页面[重复]