全局数组变量在线程中丢失值

Global array variable loses values in thread

本文关键字:线程 数组 变量 全局      更新时间:2023-10-16

我正在开发一个小应用程序,它首先向定义为全局变量的指针数组添加一些值:

#define MAX_LOCATIONS 32
LocationDTO* locations[MAX_LOCATIONS];
int nLocations = 0;

我使用以下方法将LocationDTO对象引用添加到数组:

bool addLocation(Location *location, string name){
    LocationDTO l(name, location);
    if(nLocations < MAX_LOCATIONS){
        locations[nLocations] = &l;
        nLocations++;
        return true;
    }else{
        return false;
    }
}

我用这种方式从主方法调用这个函数:

Location l1(1,2);
addLocation(&l1, "one");
Location l2(2,3);
addLocation(&l2, "two");
Location l3(4,5);
addLocation(&l3, "three");

添加完所有值后,我启动一个线程来处理这个数组。线程定义:

void* server_thread(void* args){
    // Some code
    int i;
    for(i=0; i < nLocations; i++){
        LocationDTO* l = locations[i];
        // More Code
    }
} 

问题是,在线程的这一点上,locations中包含的对象不再具有我分配给它们的值。

发生这个问题是因为我在addLocation内创建对象,然后将引用保存在数组中吗?

是的,你是对的。离开addLocation方法时,LocationDTO l变量将被销毁。

我认为这个问题几乎没有可能的解决方案:第一个解决方案:

std::vector<LocationDTO> locations;
const size_t maxSize = 32;
bool addLocation(Location *location, string name)
{
    if( locations.size() < maxSize )
    {
        locations.emplace_back( name, location );
        return true;
    }
    return false;
}

第二种解决方案:

bool addLocation(Location *location, string name){
    LocationDTO* l = new LocationDTO(name, location);
    if(nLocations < MAX_LOCATIONS){
        locations[nLocations] = l;
        nLocations++;
        return true;
    }else{
        return false;
    }
}

如果您决定使用第二个解决方案,请不要忘记删除所有分配的LocationDTO对象

addLocation中,您正在创建一个局部变量l,并将l的地址存储在全局数组中。在addLocation结束时,addLocation中的任何局部变量在被销毁时都将变为无效。曾经是l的地址处的存储器可以并且将用于其他数据。您必须使用某种形式的动态内存分配,以允许该位置的内存保持在addLocation函数的范围之外。

您似乎在堆栈上创建了这些对象,并将指针传递给addLocation()方法。当您离开作用域(退出函数)时,这些对象将被销毁。启动线程时,你确定这些对象存在吗?

试试这个:

addLocation(new Location(1,2), "one");
addLocation(new Location(2,3), "two");
addLocation(new Location(4,5), "three");

当然,你以后必须销毁这些物体。

问题是,在线程的这一点上,包含在位置中的对象不再具有我分配给它们的值。

您的locations数组不包含LocationDTO对象。它包含指向对象的指针

发生这个问题是因为我在addLocation中创建对象,然后将引用保存在数组中吗?

是的,差不多。更确切地说,您的错误是将locations中的指针指向一个自动变量。当自动变量超出范围时(在这种情况下是在addLocation的末尾),并且在此之后指针不再指向有效对象时,它们就会被销毁。引用与指针不同,但这也适用于它们。

避免内存处理错误的最简单方法是让标准库来处理它。我建议您使用std::vector<LocationDTO> locations;