内存仅在gcc上发生意外更改

Memory altered unexpectedly only on gcc?

本文关键字:意外 gcc 内存      更新时间:2023-10-16

在下面的代码中,char* d的内存地址在100ms后发生了更改,我没有做任何更改。有人能解释一下下面代码中哪里是未定义的行为吗?

此行为仅在gcc 4.8.2上可见,在visualstudio 2012上不可见。

#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include <chrono>
using namespace std;
class state_p
{
public:
    unsigned char* state;
    void init(unsigned char* state_in)
    {
        state = state_in;
    }
};
void state_link(unsigned char* &state)
{
    for(unsigned int i = 0; i < 10; i++)
    {
        state_p s;
        s.init(state+184*i);
    }
}
void go_sleep(unsigned int ms)
{
    boost::this_thread::sleep(boost::posix_time::milliseconds(ms));
}
class main_class
{
private:
    char *d;
    unsigned s;
    char* a;
    void core()
    {
        while(true)
        {
            cout << "A_CORE: " << (void*)d << "n";
        }
    }
public:
    main_class() {}
    main_class(char *di)
    {
        d = di;
        boost::thread start_core_thread(&main_class::core, this);
    }
};
void show(unsigned int &i)
{
    cout << i;
    go_sleep(100000000);
}
int main()
{
    unsigned char *state = (unsigned char*)calloc(3072, sizeof(char));
    char st = 100;
    main_class main_c;
    main_c = main_class(&st);
    state_link(state);
    go_sleep(100);
    unsigned int i = 0;
    show(i);
}

输出:

A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0x186a0
A_CORE: 0
A_CORE: 0
A_CORE: 0
A_CORE: 0

此处:

main_c = main_class(&st);

创建并销毁临时main_class,然后将其复制到main_c。此处:

boost::thread start_core_thread(&main_class::core, this);

将指向该临时对象的指针绑定到线程。线程在它被破坏后继续访问它,从而产生未定义的行为。特别是,如果临时对象的存储被重新用于另一个对象,您很可能会看到值的变化。

如果您要直接初始化非临时对象:

main_class main_c(&st);

那么您应该回到定义良好的行为领域。您可以考虑使类不可复制,以防止出现此错误。

您还应该显式分离线程,或者将其作为类成员保留以稍后加入。Boost中不赞成在不连接或分离线程对象的情况下销毁线程对象,而在标准库中则禁止销毁线程对象。