Бойтесь alloca
От: rm822 Россия  
Дата: 26.03.07 10:39
Оценка: 79 (11)
Что такое alloca я думаю объяснять никому не надо — функция выделения памяти на стеке.
Плюсы:
— быстро
— не нужно освобождать
Грабли:
— много не выделишь

for(.......)
{
  char* = (char*)alloca(bytesCount);
}

приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope и в зависимости от количества итераций стек может кончиться а может и нет
— неуловимый баг
CComBSTR bs = ........;
CString s = ...........;
for(.......)
{
  if (bs == s)
    {
      ......
        break;
    }
}

Казалось бы ничто не предвещает беды, но все-таки этот код МОЖЕТ содержать баг.
bs == s вызывает bool CComBSTR::operator==(LPCSTR pszSrc) const
    bool CComBSTR::operator==(LPCSTR pszSrc) const
    {
        if (pszSrc == NULL && m_str == NULL)
            return true;
        USES_CONVERSION; 
        if (pszSrc != NULL && m_str != NULL)
            return wcscmp(m_str, A2W(pszSrc)) == 0; //A2W - cодержит alloca
        return false;
    }


так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator==
инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Бойтесь alloca
От: red_dragon Украина  
Дата: 26.03.07 10:43
Оценка: :)
Здравствуйте, rm822, Вы писали:

что-бы небыло багов, пользуемся new, delete
Re: Бойтесь alloca
От: ilnar Россия  
Дата: 26.03.07 10:47
Оценка:
Давайте все же говорить "ПРЕДОСТЕРЕГАЙТЕСЬ", и ставить как deprecate
Re[2]: Бойтесь alloca
От: Bell Россия  
Дата: 26.03.07 11:04
Оценка:
Здравствуйте, ilnar, Вы писали:

I>Давайте все же говорить "ПРЕДОСТЕРЕГАЙТЕСЬ", и ставить как deprecate


Так уж и deprecate? Быть может уже есть адекватная замена?
Любите книгу — источник знаний (с) М.Горький
Re: Бойтесь alloca
От: Bell Россия  
Дата: 26.03.07 11:05
Оценка:
Здравствуйте, rm822, Вы писали:

Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток.
Любите книгу — источник знаний (с) М.Горький
Re[2]: Бойтесь alloca
От: rm822 Россия  
Дата: 26.03.07 11:11
Оценка: +1
Здравствуйте, Bell, Вы писали:

B>Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток.

В данном случае ты не управляешь молотком, сначала он тебя ударит по пальцам а потом и по башке может садануть.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 26.03.07 11:14
Оценка: 5 (2)
Здравствуйте, rm822, Вы писали:

R>приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope и в зависимости от количества итераций стек может кончиться а может и нет


RTFM man alloca:

DESCRIPTION
The alloca() function allocates size bytes of space in the stack frame of
the caller. This temporary space is automatically freed on return.


Память освобождается при выходе их функции, не при выходе из скопа. Так что тут ты просто некорректно используешь.
То, что размер надо проверять, это само сабой — произвольный размер туда передавать нельзя.




R>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator==

R>инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.

Вот это, конечно, неприятно, если это действительно так...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Бойтесь alloca
От: ilnar Россия  
Дата: 26.03.07 11:16
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, rm822, Вы писали:


B>Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток.


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

а вообще, функция из эпохи, когда не было инлайнов
Re[3]: Бойтесь alloca
От: Bell Россия  
Дата: 26.03.07 11:18
Оценка:
Здравствуйте, rm822, Вы писали:

R>Здравствуйте, Bell, Вы писали:


B>>Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток.

R>В данном случае ты не управляешь молотком, сначала он тебя ударит по пальцам а потом и по башке может садануть.

Это про оператор сравнения? Тогда при чем тут alloca? Плохо, конечно, что в документации к этому оператору не указана это особенность (или указана?) но это — , ИМХО, дефект реализации/документации оператора, но никак ни средсва реализации.
Любите книгу — источник знаний (с) М.Горький
Re: Бойтесь alloca
От: Programador  
Дата: 26.03.07 11:22
Оценка:
Здравствуйте, rm822, Вы писали:

R>приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope


R> return wcscmp(m_str, A2W(pszSrc)) == 0; //A2W — cодержит alloca


В MSDN не прописано, но
1 — скопе в данном случае это всегда должно быть тело функции
2 — fun(aloca()) недопустимо, можно ptr=aloca(); fun(ptr)

Совсем непонятно что такое A2W? — где содержится результат? Пожоже у Вас какойто макрос, со слижком вольным обращением со стеком.
Re[2]: Бойтесь alloca
От: vasmann  
Дата: 26.03.07 11:28
Оценка:
Здравствуйте, Programador, Вы писали:

P>Здравствуйте, rm822, Вы писали:


R>>приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope


R>> return wcscmp(m_str, A2W(pszSrc)) == 0; //A2W — cодержит alloca


P>В MSDN не прописано, но

P>1 — скопе в данном случае это всегда должно быть тело функции
P>2 — fun(aloca()) недопустимо, можно ptr=aloca(); fun(ptr)

P>Совсем непонятно что такое A2W? — где содержится результат? Пожоже у Вас какойто макрос, со слижком вольным обращением со стеком.


A2W и W2A это два макроса, вроде из ATL а может и WTL преобразубт анси в вайдчар и вайдчар в анси соответсвенно
Спасибо.
Re[2]: Бойтесь alloca
От: rm822 Россия  
Дата: 26.03.07 11:32
Оценка:
Здравствуйте, Programador, Вы писали:
P>Совсем непонятно что такое A2W? — где содержится результат? Пожоже у Вас какойто макрос, со слижком вольным обращением со стеком.
Я то тут при чем? Не у меня а у MFC\ATL — все претензии к M$.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Бойтесь alloca
От: Programador  
Дата: 26.03.07 11:32
Оценка:
Здравствуйте, rm822, Вы писали:

R>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator==

R>инлайнится.
А где тело ператора — прямо в классе?
Re[2]: Бойтесь alloca
От: Programador  
Дата: 26.03.07 11:52
Оценка:
Здравствуйте, Programador, Вы писали:
Посмотрел A2W. МС нарушает fun(aloca()). Вообще смысл этого ограничения в том что стек меняется в процессе проталкивания. Правда там алока первым параметрои идет, наверно поэтому прокатывает.
Так где оператор описан?
Re[3]: Бойтесь alloca
От: Programador  
Дата: 26.03.07 11:53
Оценка:
А у Вас еще внутри другой функции
Re[2]: Бойтесь alloca
От: rm822 Россия  
Дата: 26.03.07 12:05
Оценка:
R>Вот это, конечно, неприятно, если это действительно так...
Reproduced!
здесь

характерно что на VC6 чтобы упасть ему нужен Inline
а на VS2005 этот инлайн можно смело убрать и он все равно падает.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Не в том проблема
От: degor Россия  
Дата: 26.03.07 12:05
Оценка:
завязывайте уже с шестой студией. в семерке эти грабли с CComBSTR и A2W разобраны.

R>
R>    bool CComBSTR::operator==(LPCSTR pszSrc) const
R>    {
R>        if (pszSrc == NULL && m_str == NULL)
R>            return true;
R>        USES_CONVERSION; 
R>        if (pszSrc != NULL && m_str != NULL)
R>            return wcscmp(m_str, A2W(pszSrc)) == 0; //A2W - cодержит alloca
R>        return false;
R>    }
R>
Re[4]: Бойтесь alloca
От: Кодт Россия  
Дата: 26.03.07 13:06
Оценка: +3
Здравствуйте, Bell, Вы писали:

B>Это про оператор сравнения? Тогда при чем тут alloca? Плохо, конечно, что в документации к этому оператору не указана это особенность (или указана?) но это — , ИМХО, дефект реализации/документации оператора, но никак ни средсва реализации.


Это дефект компилятора, который инлайнит функцию, содержащую alloca(), и не вставляет туда код по восстановлению стека.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: Бойтесь alloca
От: Кодт Россия  
Дата: 26.03.07 13:06
Оценка: +1
Здравствуйте, remark, Вы писали:

R>Память освобождается при выходе их функции, не при выходе из скопа. Так что тут ты просто некорректно используешь.

R>То, что размер надо проверять, это само сабой — произвольный размер туда передавать нельзя.

R>>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator==

R>>инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.

R>Вот это, конечно, неприятно, если это действительно так...


Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Бойтесь alloca
От: Programador  
Дата: 26.03.07 13:10
Оценка:
Здравствуйте, rm822, Вы писали:

R>>Вот это, конечно, неприятно, если это действительно так...

R>Reproduced!
R>здесь

R>характерно что на VC6 чтобы упасть ему нужен Inline

R>а на VS2005 этот инлайн можно смело убрать и он все равно падает.

Да — действительно ::MessageBox(0,"shit","shit",0);

Попробовал стек в зад вернуть

struct Sppp
{  unsigned int psppp;
 __inline  Sppp(){
         __asm  mov   dword ptr  [this+psppp],esp;
       }
__inline ~Sppp(){
         __asm  mov   esp, dword ptr  [this+psppp];
       }
};

Так оно не инлайнется. И вообще проек сломался.
А вызовы там такие интересные — хелпер к алоке и еще стек и коки чекеры и т.д.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.