2009-04-09 5 views
8

Я разрабатываю Windows с DevStudio, в C/C++ неуправляемый.Звонок на _freea действительно нужен?

Я хочу выделить некоторую память в стеке вместо кучи, потому что я не хочу иметь дело с выпуском этой памяти вручную (я знаю об умных указателях и обо всех этих вещах. У меня очень конкретный случай распределение памяти, с которым мне нужно иметь дело), ​​аналогично использованию макросов A2W() и W2A().

_alloca делает это, но он устарел. Предлагается вместо этого использовать malloca. Но документация _malloca говорит, что звонок ___freea является обязательным для каждого звонка _malloca. Затем он побеждает мою цель использовать _malloca, вместо этого я буду использовать malloc или new.

Кто-нибудь знает, смогу ли я уйти без вызова _freea без утечки и какие воздействия будут внутренне?

В противном случае, я буду использовать только устаревшую функцию _alloca.

ответ

13

Всегда важно называть _freea после каждого вызова _malloca.

_malloca похоже на _alloca, но добавляет некоторые дополнительные проверки безопасности и усовершенствования для вашей защиты. В результате, возможно, что _malloca будет выделять кучу вместо стека. Если это произойдет, и вы не вызываете _freea, вы получите утечку памяти.

В режиме отладки _malloca ALWAYS выделяет кучу, поэтому ее также нужно освободить.

Искать _ALLOCA_S_THRESHOLD для получения информации о том, как работают пороги, и почему _malloca существует вместо _alloca, и это должно иметь смысл.


Edit:

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

Есть преимущества в стек распределения, который _malloca предоставит вам , поэтому есть причины для этого. _alloca будет работать одинаково, но, скорее всего, вызовет переполнение стека или другую проблему, и, к сожалению, не дает хороших исключений, а скорее просто срывает ваш процесс. _malloca намного безопаснее в этом отношении и защищает вас, но стоимость в том, что вам все равно нужно освободить свою память с помощью _freea, так как это возможно (но маловероятно в режиме выпуска), который _malloca будет выбирать для размещения в куче вместо стека.

Если ваша цель состоит в том, чтобы избежать свободной памяти, я бы рекомендовал использовать интеллектуальный указатель, который будет обрабатывать освобождение памяти для вас, поскольку член выходит за рамки. Это назначит память в куче, но будет безопасным и не позволит вам освободить память. Это будет работать только на C++, но если вы используете plain ol 'C, этот подход не будет работать.

Если вы пытаетесь выделить в стеке по другим причинам (как правило, производительность, так как распределение стека очень и очень быстро), я бы рекомендовал использовать _malloca и жить с тем фактом, что вам нужно будет называть _freea на вашем значения.

+1

Просто любопытно, но почему downvotes на Mitch и мои сообщения? Я хотел бы знать, почему кто-то не согласен с этим комментарием ... особенно если я что-то упускаю. –

1

Чтобы выделить память в стеке, просто объявите переменную соответствующего типа и размера.

+0

Почему нижний предел? Плакат спросил о стеке ... –

+0

Это был не мой нисходящий сигнал, но я предполагаю, что он просто спрашивал о _alloca/_malloca, у которого очень разные шаблоны использования стека, чем объявления стандартной переменной. Лично я тоже буду голосовать за вас, потому что в большинстве случаев это то, что я делаю, если это возможно. –

+0

@Reed Copsey: спасибо. –

0

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

template <class T> 
class TempMem 
{ 
    TempMem(size_t size) 
    { 
    mAddress = new T[size]; 
    } 

    ~TempMem 
    { 
    delete [] mAddress; 
    } 

    T* mAddress; 
} 

void foo(void) 
{ 
    TempMem<int> buffer(1024); 

    // alternatively you could override the T* operator.. 
    some_memory_stuff(buffer.mAddress); 

    // temp-mem auto-freed 
} 
3

Другая вещь, чтобы рассмотреть использует класс RAII для управления распределением - конечно, это только полезно, если ваш макрос (или любой другой) может быть ограничено C++.

Если вы хотите избежать удара кучи по соображениям производительности, взгляните на методы, используемые шаблоном Matthew Wilson's auto_buffer<> (http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html). Это будет выделяться в стеке, если ваш запрос размера времени выполнения не превышает размер, указанный во время компилятора, поэтому вы получаете скорость без кучи для большинства распределений (если вы правильно изменяете шаблон), но все по-прежнему работает правильно, если ваше превышение это размер.

Поскольку STLsoft имеет целую кучу хлама для решения вопросов мобильности, вы можете захотеть взглянуть на более простой версии auto_buffer<>, которая описана в книге Уилсона, "Imperfect C++".

Я нашел, что это очень удобно во встроенном проекте ,

+1

+1 в предложении auto_buffer <>. Это в основном делает то, что _malloca делает вместо _alloca на окнах. Существует проверка, чтобы убедиться, что вы не ударите свой лимит стека, и при необходимости, вместо распределения стека он будет распределять кучи. Это тоже работает на C. –

1

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

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

Я вернулся и принял другой подход, в результате чего была использована комбинация использования макроса (eurgh) для выделения памяти и создания экземпляра объекта, который будет автоматически вызывать _freea в этой памяти. Поскольку это макрос, он выделяется в том же стеке стека, и поэтому будет работать в режиме деблокирования. Это так же удобно, как и мой класс, но немного менее приятным в использовании.

я сделал следующее:

class EXPORT_LIB_CLASS CAutoMallocAFree 
{ 
public: 
    CAutoMallocAFree(void *pMem) : m_pMem(pMem) {} 
    ~CAutoMallocAFree() { _freea(m_pMem); } 

private: 
    void *m_pMem; 

    CAutoMallocAFree(); 
    CAutoMallocAFree(const CAutoMallocAFree &rhs); 
    CAutoMallocAFree &operator=(const CAutoMallocAFree &rhs); 
}; 

#define AUTO_MALLOCA(Var, Type, Length) \ 
    Type* Var = (Type *)(_malloca((Length) * sizeof (Type))); \ 
    CAutoMallocAFree __MALLOCA_##Var((void *) Var); 

Таким образом, я могу выделить с помощью следующего макроса вызова, и она будет выпущена, когда проиллюстрированный класса выходит из области видимости:

  AUTO_MALLOCA(pBuffer, BYTE, Len); 
      Ar.LoadRaw(pBuffer, Len); 

Мои извинения за публикации что-то совершенно неправильное!

0

Если вы используете _malloca(), тогда вы должны позвонить _freea(), чтобы предотвратить утечку памяти, поскольку _malloca() может выполнять выделение либо на стеке, либо на куче. Он прибегает к распределению в куче, если заданный размер превышает значение_ALLOCA_S_THRESHOLD. Таким образом, безопаснее позвонить _freea(), который ничего не сделает, если распределение произошло в стеке.

Если вы используете _alloca(), который, как представляется, устарел на сегодняшний день; нет необходимости вызывать _freea(), поскольку распределение происходит в стеке.