2015-02-19 5 views
1

Я занимаюсь разработкой небольшое приложение, которое первым добавляет некоторые значения в массив указателей определяется как глобальная переменная:Глобальная переменная массив теряет значения в потоке

#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 не имеет больше значения I, возложенный на них.

Возникает ли эта проблема, потому что я создаю объекты внутри addLocation, а затем сохраняю ссылку в массиве?

+0

l - локальная переменная. Он исчезает, когда функция заканчивается. Если вы хотите сохранить значение между вызовами, используйте новый оператор для выделения памяти в куче. – caveman

ответ

2

Да, вы правы. Параметр LocationDTO l будет уничтожен, когда вы оставите метод addLocation.

я вижу несколько возможных решений этой проблемы: первого решения:

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 объекты

0

В addLocation вы создаете локальную переменную l и сохраняете адрес l в своем глобальном массиве. В конце addLocation любые локальные переменные в addLocation становятся недействительными по мере их уничтожения. Память по адресу того, что когда-то была l, может и будет использоваться для других данных. Вы должны использовать некоторую форму распределения динамической памяти, чтобы память в этом месте сохранялась за пределами функции addLocation.

0

Кажется, что вы создаете эти объекты в стеке и передаете указатели на метод addLocation(). Эти объекты уничтожаются, когда вы покидаете область действия (функция выхода). Вы уверены, что эти объекты существуют при запуске потока?

Попробуйте это:

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

Конечно, вы должны уничтожить эти объекты позже.

0

Проблема в том, что в данный момент в потоке объекты, содержащиеся внутри местоположений, больше не имеют значений, которые я им назначил.

Ваш locations массив не содержит LocationDTO объектов. Он содержит указателей к объектам.

Возникает ли эта проблема из-за того, что я создаю объекты внутри addLocation, а затем сохраняю ссылку в массиве?

Да, почти. Точнее, ваша ошибка заключается в том, что вы указываете указатель в locations на автоматическую переменную. Автоматические переменные уничтожаются, когда они выходят за пределы области (в конце addLocation в этом случае), и после этого указатели больше не указывают на действительный объект. Ссылки - это не то же самое, что указатели, но это также относится к ним.

Самый простой способ избежать ошибок при работе с памятью - позволить стандартной библиотеке позаботиться об этом.Я рекомендую использовать std::vector<LocationDTO> locations;

Смежные вопросы