У меня есть два класса, похожие на это:
class A
{
public:
B* ptr1;
}
class B
{
public:
std::vector<A*> list;
}
В основной реализации я делаю что-то вроде этого:
int main() {
// there are a lot more A objects than B objects, i.e. listOfA.size() >>> listOfB.size()
std::vector<A> listOfA;
std::vector<B> listOfB;
while (//some loop)
{
listOfB[jj].list.push_back( &(listofA[ii]) );
listOfA[ii].ptr1 = &( listOfB[jj] );
}
} // int main end
В основном как то так. Много объектов A назначаются одному объекту B, и эти объекты A сохраняются в этом векторе указателей как указатели. Кроме того, каждый из этих объектов A получает указатель на объект B, которому он принадлежит. Для контекста я в основном делаю Алгоритм связанных компонентов с кодированием по длине прогона (для сегментации изображения), где класс A — это отрезки линии, а класс B — конечные объекты в изображении.
Таким образом, все указатели на вектор в классе B указывают на объекты, которые хранятся в регулярном векторе. Эти объекты должны быть удалены, когда обычный вектор выходит из области видимости, верно? Я читал, что вектор указателя, как в классе B, обычно требует написания ручного деструктора, но, думаю, этого не должно быть …
Причина, по которой я спрашиваю, заключается в том, что мой код продолжает падать. Я использую камеру Asus Xtion Pro, чтобы получить изображения, а затем выполняю алгоритм для каждого изображения. Странно то, что программа вылетает всякий раз, когда я немного встряхиваю камеру. Когда камера неподвижна или перемещается немного или медленно, ничего не происходит. Кроме того, когда я использую другой алгоритм (также подключенные компоненты, но без кодировки длин серий, а также не использую указатели), ничего не происходит, независимо от того, насколько сильно я трясу камеру. Кроме того, в режиме отладки (который работал намного медленнее, чем в режиме выпуска), ничего не происходило.
Я попытался создать деструктор для вектора указателя в классе B, но это привело к ошибке «блок действителен», поэтому я думаю, что он дважды что-то удалил.
Я также пытался заменить каждый указатель с помощью c ++ 11 std :: shared_ptr, но это приводило к очень нерегулярному поведению, и код все еще падал, когда я тряс камеру.
Я просто хочу знать, выглядит ли приведенный выше код с точки зрения утечки памяти и обработки указателей нормальным или есть ошибки в коде, которые могут привести к сбоям.
РЕДАКТИРОВАТЬ (РЕШЕНО): Решение (см. Принятый ответ) состояло в том, чтобы гарантировать, что вектор «listOfB» не будет изменен во время выполнения, например, с помощью «reserve ()», чтобы зарезервировать для него достаточно места. После этого все работало нормально! Очевидно, это сработало, потому что, если вектор ‘listOfB’ изменяется (с помощью push_back ()), адреса внутренней памяти экземпляров B в нем также изменяются, в результате чего указатели в экземплярах A (которые указывают на экземпляры B) теперь указать на неправильные адреса — и тем самым привести к неприятностям, которые приводят к аварии.
Что касается сотрясения камеры, то, очевидно, сотрясение камеры привело к получению очень размытых снимков с большим количеством элементов для сегментирования, что привело к увеличению количества объектов (т. Е. К увеличению размера, необходимого для listOfB). Итак, тайна раскрыта! Большое спасибо! 🙂
Я думаю, что дизайн сломан. listofB будет расти (вы выполняете push_backs) и перераспределяете свой внутренний массив данных, делая недействительными все адреса, хранящиеся в ptrs экземпляров A. Обычный алгоритм увеличит размер данных в 2 раза, что может объяснить, что вы хороши какое-то время, если поступает не слишком много данных. Кроме того, до тех пор, пока память старых данных все еще находится в адресном пространстве программы (особенно если она находится на той же странице памяти, например, потому что новые данные также помещаются в нее), программа может не получить аварийного доступа это и просто восстановить старые данные.
На более конструктивном примечании: ваше решение будет работать, если вы заранее знаете максимальное количество элементов, что может быть сложно (думаю, вы получите камеру 4k в следующем году ;-)). В этом случае, между прочим, вы можете просто взять простой статический массив.
Возможно, вы могли бы также использовать std::map
хранить объекты A вместо простого векторного списка A. Каждому объекту A потребуется уникальный идентификатор некоторого вида (статический счетчик в A в простейшем случае) для использования в качестве ключа на карте. Bs будет хранить ключи, а не адреса As.
Если вы не ошиблись в том, как строили свою сеть, у вас все будет хорошо. Вы должны были бы опубликовать больше кода, чтобы оценить это. Также вы не можете использовать любой из векторы после изменения одного из них, потому что, если они перераспределяют своих членов, все указатели, указывающие на них, становятся недействительными. Но используя сырые указатели в управляемые объекты правильный способ построить сети.
От управляемые объекты Я имею в виду объекты, срок жизни которых гарантированно дольше, чем сеть, и чья память будет автоматически освобождена. Таким образом, они должны быть элементами контейнера или объектов, управляемых каким-либо умный указатель.
Однако, похоже, у вас проблемы с оборудованием.