В Windows я заметил, что попытка разыменования указателя на недавно освобожденную память приводит к сбою, пойманному Visual Studio, утверждающим, что память недействительна. Это как и ожидалось. Однако выполнение того же приложения и пути к коду, которые приводят к разыменованию указателя на недавно освобожденную память, не сразу вызывает сбой в Linux. Это говорит мне о том, что ядро Linux (или среда выполнения GNU C ++) не делает недействительными освобожденную память очень быстро, даже при отладочных сборках. Приложение требует гораздо больше времени для сбоя. Это тот случай? Если это так, могу ли я заставить память быстрее отображаться? Если нет, то что происходит?
Ты пытался http://valgrind.org/? Его цель — помочь отследить проблемы, подобные той, которую вы описали.
Большинство реализаций new
/delete
не возвращать память
немедленно в систему, или, по крайней мере, не возвращать меньше
блоки. Я довольно удивлен, что ваш код потерпел крах под
Windows просто разыменовывает указатель на память; ты
уверен, что вы не сделали больше этого (например, используйте значение, которое вы прочитали
через указатель).
Насколько большой был блок? Многие реализации используют разные
стратегии в зависимости от размера блока, и будет свободным
очень большие блоки сразу. (IIRC, Linux сделает mmap
сразу для очень больших блоков, и сразу же отключите его, когда
Вы освобождаете это. Конечно, если вы перераспределяете память между
свободный и разыменование указателя, возможно, что
адрес находится во вновь выделенном пространстве, и он не потерпит крах.)
В конце концов, гранулярность отображения — это страница, а вы
не может ожидать, что распределитель заблокирует полную страницу для каждого
Распределение, просто так, что это может сделать недействительной память
немедленно на освобождение. (Страница, вероятно, по крайней мере 4K,
и вы не хотите терять 4K адресного пространства каждый раз, когда вы
выделить 16 байт.) Если не отслеживать все обращения к памяти (например,
ValGrand или Purify), и работает намного медленнее, единственный
альтернативой является использование сборки мусора, чтобы гарантировать, что
память не перераспределяется, пока на нее есть указатель,
и полностью перезаписать его при освобождении (т.е. в delete
или же free
) со значениями, которые могут вызвать проблемы при использовании
(0xDEADBEEF
, или что-то типа того). И даже тогда ты
на самом деле не гарантировано, что вы потерпите крах0xDEADBEEF
мог
быть действительным значением того, что вы думаете, что читаете. (Но это
позволяет, например, установка флага в конструкторе, сброс его
в деструкторе, и проверяя его в каждой функции. Для кода
это должно быть активно оборонительным.)