Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Ограничение используемой программой памяти


Автор: rudvil 3.4.2010, 00:04
Нужно как-то ограничить используемую программой память, например как в php.
Выставил в настройках скажем "20 мб" и выше этой планки программа потреблять памяти не будет.
Насколько я понимаю, мне нужно перегрузить используемый мною оператор "new" / "delete", и при каждой попытке выделении памяти, увеличивать счетчик, ну и при удалении уменьшать счетчик соотвественно...
С "new" проблем не возникло...
Код
void* operator new (std::size_t size) {
    /*
    тут проверка - не превысется ли лимит... при malloc
    */
    currentMemory += size;
    void* mem = std::malloc(size);
    if (!mem)
        ail::fatal_error("\n[ALLOCATING FAILED]\n");
    return mem;
}

void* operator new[] (std::size_t size) {
    /*
    тут проверка - не превысется ли лимит... при malloc
    */
    currentMemory += size;
    void* mem = std::malloc(size);
    if (!mem)
        ail::fatal_error("\n[ALLOCATING FAILED]\n");
    return mem;
}

не могу нигде найти информацию по этому...
Код
void operator delete (void* mem) {
    std::free(mem);
}

void operator delete[] (void* mem) {
    std::free(mem);
}

т.е. как в этих случаях можно узнать размер удаляемого блока("mem")?
Чтобы можно было уменьшить счетчик используемой памяти...

з.ы. операторы перегружаю глобально

Автор: 586 3.4.2010, 02:37
http://msdn.microsoft.com/en-us/library/z2s077bc%28VS.80%29.aspx

Автор: rudvil 3.4.2010, 11:41
Цитата(586 @ 3.4.2010,  01:37)
http://msdn.microsoft.com/en-us/library/z2s077bc%28VS.80%29.aspx

Спасибо, то что нужно  smile 
Но это как я понял только под винду =/ есть ли кроссплатформенные аналоги этой структуры?

Автор: Rickert 3.4.2010, 16:35
А я бы не писал перегрузку new/delete - это слишком тонкая штука, с которой легко ошибиться.
Вместо этого я бы создал свои классы, которые бы сами выделяли память и чистили её, под определённые типы данных (массивы, списки т.п.)? при этом держали бы объём в постоянном сравнении с максимальной величиной. Кроссплатформенно и безопасно smile 

Автор: rudvil 4.4.2010, 15:20
Цитата(Rickert @ 3.4.2010,  15:35)
А я бы не писал перегрузку new/delete - это слишком тонкая штука, с которой легко ошибиться.
Вместо этого я бы создал свои классы, которые бы сами выделяли память и чистили её, под определённые типы данных (массивы, списки т.п.)? при этом держали бы объём в постоянном сравнении с максимальной величиной. Кроссплатформенно и безопасно smile

Возможно я так и поступлю, спасибо.
Хотелось бы узнать как можно ошибиться если я использую всеголишь malloc и free...?

Автор: jonie 4.4.2010, 16:02
можно еще глянуть на альтернативные менеджеры памяти: http://stackoverflow.com/questions/858592/windows-malloc-replacement-e-g-tcmalloc-and-dynamic-crt-linking

возможно, в них уже есть встроенные фичи, которые вам нужны...

Автор: bsa 6.4.2010, 17:03
Цитата(rudvil @  3.4.2010,  00:04 Найти цитируемый пост)
т.е. как в этих случаях можно узнать размер удаляемого блока("mem")?

Можно поступить так:
оператор new выделяет на 4 + sizeof(size_t) памяти больше, чем от него требуется. В первые четыре байта записывается некоторая сигнатура, затем записывается размер полезного блока памяти. Вызывающей функции возвращается указатель со смещением на 4 + sizeof(size_t) байт.
оператор delete проверяет сигнатуру удаляемого блока памяти, вычитает размер из счетчика, вызывает free.
Как вариант, можно сделать два вида сигнатур для new/delete и new[]/delete[] соответственно. Таким образом, будет дополнительная проверка правильности использования данных операторов.

Хотя, правильнее всего использовать "менеджеры" памяти, о которых говорил Rickert, тем более, что даже контейнеры STL их поддерживают.

Автор: rudvil 7.4.2010, 10:26
Цитата(bsa @ 6.4.2010,  16:03)
Цитата(rudvil @  3.4.2010,  00:04 Найти цитируемый пост)
т.е. как в этих случаях можно узнать размер удаляемого блока("mem")?

Можно поступить так:
оператор new выделяет на 4 + sizeof(size_t) памяти больше, чем от него требуется. В первые четыре байта записывается некоторая сигнатура, затем записывается размер полезного блока памяти. Вызывающей функции возвращается указатель со смещением на 4 + sizeof(size_t) байт.
оператор delete проверяет сигнатуру удаляемого блока памяти, вычитает размер из счетчика, вызывает free.
Как вариант, можно сделать два вида сигнатур для new/delete и new[]/delete[] соответственно. Таким образом, будет дополнительная проверка правильности использования данных операторов.

Хотя, правильнее всего использовать "менеджеры" памяти, о которых говорил Rickert, тем более, что даже контейнеры STL их поддерживают.

А вот это уже интересно...
2bsa, ваш вариант понравился больше всего, начну его использовать.
Всем большое спасибо за помощь, решение найдено. smile

Автор: rudvil 7.4.2010, 13:08
Возник ещё 1 вопрос   smile , а именно - вот код
Код
void *malloc_hook(size_t size) {
    void *ptr = malloc(size + sizeof(size_t));
    *(size_t *) ptr = size;
    return ((size_t *) ptr) + 1;
}

void free_hook (void *ptr) {
    ptr = (void *) (((size_t *) ptr) - 1);
    free(ptr);
}

size_t report_size(void* ptr) {
    return * (((size_t *) ptr) - 1);
}
это реализация как-раз того о чем писал bsa.
http://stackoverflow.com/questions/1208644/how-can-i-get-the-size-of-a-memory-block-allocated-using-malloc/1208728#1208728.
Код рабочий, всё ок.
Я только не пойму одного, зачем добавлять + 1 если мы и так уже сместили указатель выделяемого блока на (size_t*) ?

Автор: bsa 7.4.2010, 14:29
Цитата(rudvil @  7.4.2010,  13:08 Найти цитируемый пост)
Я только не пойму одного, зачем добавлять + 1 если мы и так уже сместили указатель выделяемого блока на (size_t*) ?
ткни пальцем в ту строку, где произошло первое смещение?
Кстати, я бы не изменял size на размер size_t, так как в последующих вычислениях придется постоянно вычитать.

Автор: rudvil 7.4.2010, 15:45
Цитата(bsa @ 7.4.2010,  13:29)
Цитата(rudvil @  7.4.2010,  13:08 Найти цитируемый пост)
Я только не пойму одного, зачем добавлять + 1 если мы и так уже сместили указатель выделяемого блока на (size_t*) ?
ткни пальцем в ту строку, где произошло первое смещение?
Кстати, я бы не изменял size на размер size_t, так как в последующих вычислениях придется постоянно вычитать.

Извиняюсь, ступил... все верно.
А насчет вычислений, я не имею ничего против вычитаний. =]

Автор: bsa 7.4.2010, 16:49
Цитата(rudvil @  7.4.2010,  15:45 Найти цитируемый пост)
А насчет вычислений, я не имею ничего против вычитаний.
Это называется пессимизация - т.е. выполнение лишних операций.

Автор: rudvil 7.4.2010, 17:12
Цитата(bsa @ 7.4.2010,  15:49)
Цитата(rudvil @  7.4.2010,  15:45 Найти цитируемый пост)
А насчет вычислений, я не имею ничего против вычитаний.
Это называется пессимизация - т.е. выполнение лишних операций.

Поначалу не так вас понял smile 
Согласен, спасибо  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)