Информация об изменениях

Сообщение Re[2]: return char* от 11.03.2017 20:22

Изменено 11.03.2017 20:31 N. I.

Re[2]: return char*
Carc:

J>>как вернуть значение локальной переменной szTmp?

C>
C>return &szTmp[0];
C>

C>Ибо, раз два плюса — то по умолчанию соглашение вызовов cdecl, то бишь освобождает стек вызывающая функция.
C>Соответственно, где-то в вызывающей функции строка вида будет валидна
C>
C>const char* const pszResult=…Sum();
C>

C>Т.к. после const char* const pszResult=… сам массив szTmp в вызываемой функции все еще будет существовать. В том смысле, что вызываемая уже отработала конечно, но вот добро ее на стеке все еще в полном порядочке лежит.

Это только один из возможных сценариев. Если компилятор начнёт оптимизировать код, результат может получиться совсем другим. Например, вызовы strcpy и strcat внутри Sum могут выброшены оптимизатором за ненадобностью, т.к. в этой функции изменённый массив szTmp нигде больше не используется, а за её пределами обращение к уничтоженному объекту уже незаконно (оптимизатору нет никакого дела до хаков, вызывающих undefined behavior, его задача действовать в рамках "as-if" rule, и выбрасывание strcpy вместе с strcat оное правило никак не нарушает). Встраивание самой Sum в код вызывающей функции тоже может привести к интересным результатам.

C>Я где-то увидел такое решение, и чуть не припух. Ибо проект был солидный, и парни там грамотные. Очень долго въезжал, что к чему. Потом стало ясно.

C>В общем, такие решения использовать можно.

В программе, которая должна работать надёжно, однозначно нельзя. При обнаружении такого кода его надо фиксить ASAP (даже если пока он "вроде бы работает").
Re[2]: return char*
Carc:

J>>как вернуть значение локальной переменной szTmp?

C>
C>return &szTmp[0];
C>

C>Ибо, раз два плюса — то по умолчанию соглашение вызовов cdecl, то бишь освобождает стек вызывающая функция.
C>Соответственно, где-то в вызывающей функции строка вида будет валидна
C>
C>const char* const pszResult=…Sum();
C>

C>Т.к. после const char* const pszResult=… сам массив szTmp в вызываемой функции все еще будет существовать. В том смысле, что вызываемая уже отработала конечно, но вот добро ее на стеке все еще в полном порядочке лежит.

Это только один из возможных сценариев. Если компилятор начнёт оптимизировать код, результат может получиться совсем другим. Например, вызовы strcpy и strcat внутри Sum могут быть выброшены оптимизатором за ненадобностью, т.к. в этой функции изменённый массив szTmp нигде больше не используется, а за её пределами обращение к уничтоженному объекту уже незаконно (оптимизатору нет никакого дела до хаков, вызывающих undefined behavior, его задача действовать в рамках "as-if" rule, и выбрасывание strcpy вместе с strcat оное правило никак не нарушает). Встраивание самой Sum в код вызывающей функции тоже может привести к интересным результатам.

C>Я где-то увидел такое решение, и чуть не припух. Ибо проект был солидный, и парни там грамотные. Очень долго въезжал, что к чему. Потом стало ясно.

C>В общем, такие решения использовать можно.

В программе, которая должна работать надёжно, однозначно нельзя. При обнаружении такого кода его надо фиксить ASAP (даже если пока он "вроде бы работает").