Используются ли адреса памяти в куче повторно?

Дальнейшее объяснение вопроса заголовка в порядке, позвольте мне объяснить мой сценарий.

У меня есть список указателей на несколько объектов в куче. Всякий раз, когда создается новый объект, указатель на него добавляется в список, и всякий раз, когда объект удаляется, его указатель удаляется. Можно с уверенностью сказать, что все указатели в этом списке всегда действительны.

Многие объекты в списке содержат указатели на другие объекты в том же списке.

Прежде чем я разыменую любой из этих указателей, я хотел бы использовать функцию CheckAgainstList(ptr*), чтобы убедиться, что один объект указывает на другой объект в том же списке и, следовательно, не указывает на объект, который с тех пор был удален.

Наденьте шапочки из фольги, это возможно?

  1. Объект A имеет указатель на объект B с адресом памяти 0x00988e50.
  2. Объект Б удален.
  3. Объект C создается и помещается во вновь освобожденное пространство памяти 0x00988e50.
  4. CheckAgainstList(ptr*) возвращает true, когда мы проверяем указатель, потому что объект C находится в списке и находится в том же самом адресе памяти, который раньше занимал B.

Теперь у нас есть ошибка, потому что A думает, что у него есть указатель на B, но B ушел, а C, так сказать, занял его место.

Возможна ли эта потенциальная ошибка?


person user1438585    schedule 22.06.2012    source источник
comment
Не просто возможно - это вероятно. Если вы освобождаете B и выделяете C сразу после него, вероятно, во многих реализациях кучи вы получите тот же самый буфер сразу же.   -  person Rafael Baptista    schedule 22.06.2012
comment
Пришел сюда, чтобы узнать, как часто это происходит, увидев, что куски памяти явно используются повторно (для данных одного типа). Так да :)   -  person mlvljr    schedule 27.01.2016


Ответы (5)


Это не просто возможно, это очень вероятно. Хороший распределитель памяти будет пытаться повторно использовать память как можно чаще, чтобы уменьшить фрагментацию и раздувание.

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

person Mark Ransom    schedule 22.06.2012

Да, этот баг вполне возможен.

По сути, то, что вы делаете, довольно опасно и довольно быстро приведет к ошибкам. Возможно, вам лучше всего использовать какой-нибудь смарт-указатель с подсчетом ссылок. С++ 11 включает std::shared_ptr, что означает, что вы можете использовать его вместо обычного указателя. Таким образом, память не будет освобождена до тех пор, пока все с ней не закончится, и устранит проблемы, подобные описанным вами.

Единственным другим вариантом будет сканирование всех других объектов, чтобы увидеть, ссылаются ли они на удаленный «B», и сделать что-то вроде «обнуления» своих указателей на теперь удаленный указатель.

person Goz    schedule 22.06.2012

Адреса памяти используются повторно - в зависимости от операционной системы. В противном случае, если программа выполняет много выделений и освобождений, превышающих объем ОЗУ в машине, она не сможет продолжать работу.

В конце концов, ответ больше касается операционной системы и схемы управления памятью, чем самого C++. В конце концов, самое примитивное, что происходит, когда вы выделяете свободную (динамическую) память, заключается в том, что процесс (через стандартную библиотечную функцию) вызывает определенную подпрограмму ОС для выделения запрошенного объема памяти и возврата адреса в выделенную память.

person zxcdw    schedule 22.06.2012

Ошибка более вероятна, если вы создаете только один тип объекта. Но это всегда вполне возможно.

person Jerome    schedule 22.06.2012

Да, это может случиться. Чтобы предотвратить это, когда вы удаляете объект, пройдитесь по списку и установите любые указатели на удаленный объект, чтобы они указывали на NULL.

person Daniel    schedule 22.06.2012