Проверьте, указывает ли указатель на выделенную память на "куче"

Я хочу знать, указывает ли указатель на часть памяти, выделенной с malloc/new. Я понимаю, что ответ для произвольного адреса, "Нет Вы не можете", но я действительно думаю, что возможно переопределить malloc/free и отслеживать выделенные диапазоны памяти.

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

Valgrind является большим, но это - слишком много (медленного) инструментария и поскольку Will сказал, что мы не хотим использовать Valgrind как это (создание мягкого катастрофического отказа достаточно хорошо).
Брызговик является очень хорошим решением, но выделенный GCC, и к сожалению, проверка просто не возвращает булевскую переменную (см. мой ответ ниже).
Обратите внимание, что проверка, что записи памяти законны, является проблемой безопасности. Так поиск производительности мотивирован.

15
задан log0 18 September 2013 в 08:53
поделиться

8 ответов

Нет стандарта способ сделать это, но различные инструменты отладки malloc могут иметь способ сделать это. Например, если вы используете valgrind , вы можете использовать VALGRIND_CHECK_MEM_IS_ADDRESSABLE , чтобы проверить это и связанные с ним вещи

10
ответ дан 1 December 2019 в 02:01
поделиться

Доказательство того, что, вероятно, не удастся сделать с пользой:

char * p1 = malloc(1);
free( p1 );
char * p2 = malloc(1);   // probably allocates same block as first malloc

Теперь и p1, и p2 указывают на одну и ту же память в куче, но действителен только p2.

12
ответ дан 1 December 2019 в 02:01
поделиться

Вы можете использовать LD_PRELOAD и обернуть malloc внутри своей собственной функции.

1
ответ дан 1 December 2019 в 02:01
поделиться

Вы можете сделать это сами, если производительность не является реальной проблемой для вашего приложения:

Определите MyMalloc(...) и MyFree(...), в которых, наряду с вызовом malloc/free, вы обновляете (упорядоченный) список пар {address -- результат malloc, blockSize -- объем запрашиваемой памяти }. Затем, когда вам нужно проверить указатель p, вы ищете пару, удовлетворяющую условию: адрес <= p <= адрес + blockSize.

Можно/нужно проверять и другие условия, если вы хотите действительно использовать этот указатель, это только покажет, используется ли адрес или нет.

5
ответ дан 1 December 2019 в 02:01
поделиться

Mudflap (для gcc) кажется очень милым. Вы должны скомпилировать свой софт, но он будет проверять любой неправильный доступ к указателям (куча/стек/статический). Он предназначен для работы с производственным кодом, замедление оценивается от x1.5 до x5. Вы также можете отключить проверку при доступе на чтение для увеличения скорости.
Пользовательская проверка может быть выполнена с помощью

void __mf_check (void *ptr, __mf_size_t sz, int type, const char *location)

Вызов этой функции приводит к: ничего, fork в gdb, segv или abort в зависимости от параметров окружения.

2
ответ дан 1 December 2019 в 02:01
поделиться

Выделения памяти имеют (виртуальный) адрес и длину.

Указатель содержит только адрес.

Если вы отслеживаете длину отдельно, вы можете проверить ее содержание, например:

int check_contained(const char* src,size_t srclen,const char* sub,size_t sublen) {
   return (sub >= src) && (sub+sublen < src+srclen);
}

Symbian имеет функцию AllocLen , но нет эквивалента POSIX или win32.

0
ответ дан 1 December 2019 в 02:01
поделиться

Вы можете использовать те же методы, которые использует консервативный сборщик мусора , чтобы определить, указывает ли объект, подобный указателю, на кучу или нет. В самом деле, вы, вероятно, могли бы скопировать исходный код из самого bdwgc. Это была бы нетривиальная задача, но ее можно было бы контролировать и портировать по мере необходимости. (Фактически, большая часть работы по переносу уже выполнена.)

0
ответ дан 1 December 2019 в 02:01
поделиться

Я сделал нечто подобное, но не могу вспомнить, как именно это было закодировано, и у меня нет кода под рукой.

Но основная идея заключалась в том, чтобы переопределить новый и delete для базового класса. В новый был установлен статический флаг (например, bool inDynamicAlloc = true ). Этот флаг ставится под сомнение в конструкторе базового класса. Когда это было так, объект был размещен в куче, в противном случае - в стеке.

Конструктор впоследствии сбрасывает флаг.

Надеюсь, это поможет.

0
ответ дан 1 December 2019 в 02:01
поделиться