Можно ли такое реализовать на с/с++, без ассемблерных вставок ?
Есть ли какие-нибудь расшерения с/с++, что-бы такое делать ?
1. функция funcA вызывает funcB.
2. функция funcB, решает сколько ей нужно памяти, выделяет её в стеке и заполняет данными и возвращает указатель на выделенную память.
3. сразу после возврата из funcB, мы сдвигаем регистр ESP(RSP), что-бы следующие вызовы не порушили эту память. Теперь внутри funcA мы можем безопастно использовать память выделенную в стеке funcB.
VF>Скорее всего — нет. К тому же, Вы получите ВЕСЬ стек funcB.
Да, получу весь стек, это же не страшно.
А если в funcA снова вызвать alloca, что-бы зарезервировать эту память. По сути alloca это и есть (sub rsp,ххх)
VF>Я бы выделил функцию, возвращающую нужный размер, и звал alloca по-честному из funcA
Например funcB это sprintf, она пасит шаблон (перевод числа в строки) считает сколько нужно памяти для конечной строки, выделяет память и если её тут прервать, то нужно будет парсить заново!
Этого хочу избежать.
Здравствуйте, maks1180, Вы писали:
m> Можно ли такое реализовать на с/с++, без ассемблерных вставок ? m> Есть ли какие-нибудь расшерения с/с++, что-бы такое делать ? m> 1. функция funcA вызывает funcB. m> 2. функция funcB, решает сколько ей нужно памяти, выделяет её в стеке и заполняет данными и возвращает указатель на выделенную память. m> 3. сразу после возврата из funcB, мы сдвигаем регистр ESP(RSP), что-бы следующие вызовы не порушили эту память. Теперь внутри funcA мы можем безопастно использовать память выделенную в стеке funcB.
Как освобождать стек funcB?
m>> 3. сразу после возврата из funcB, мы сдвигаем регистр ESP(RSP), что-бы следующие вызовы не порушили эту память. Теперь внутри funcA мы можем безопастно использовать память выделенную в стеке funcB. ·>Как освобождать стек funcB?
Либо обратно сдвинуть ESP(RSP) либо после выхода из funcA она автоматически освободиться.
Здравствуйте, maks1180, Вы писали:
M>1. функция funcA вызывает funcB. M>2. функция funcB, решает сколько ей нужно памяти, выделяет её в стеке и заполняет данными и возвращает указатель на выделенную память.
А почему именно стек? Исходя из описанного сценария, heap подойдёт не хуже, плюс не нужны танцы с бубном, и нет возможности испортить/атаковать стек.
Если так хочется использовать стек вместо хипа, то можно использовать стек на хипе. Единственное что его придется делать глобальным или передавать в функции. Хотя в кланге и гцц все же можно выделить отдельный регистр для этого.
Но управлять нативным стеком без жестких плясок с ассемблером вряд ли получится.
MD>А почему именно стек? Исходя из описанного сценария, heap подойдёт не хуже, плюс не нужны танцы с бубном, и нет возможности испортить/атаковать стек.
Здравствуйте, maks1180, Вы писали:
m>>> 3. сразу после возврата из funcB, мы сдвигаем регистр ESP(RSP), что-бы следующие вызовы не порушили эту память. Теперь внутри funcA мы можем безопастно использовать память выделенную в стеке funcB. M>·>Как освобождать стек funcB? M>Либо обратно сдвинуть ESP(RSP) либо после выхода
Так ты тогда и обратно сдвинешь эту твою выделенную память в стеке.
Ведь стек funcB будет выделен раньше, значит удалить фрагмент в серединке стека у тебя не выйдет.
M>из funcA она автоматически освободиться.
А если funcB будет вызываться много раз? В цикле?
Главное я не понимаю — а зачем? Вроде ты говоришь, что "выделим на стеке быстро, чтобы потом скинуть в файл". Зачем тогда вообще что-то выделять, когда можно сразу в файл кидать?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, maks1180, Вы писали:
M>Можно ли такое реализовать на с/с++, без ассемблерных вставок ? M>Есть ли какие-нибудь расшерения с/с++, что-бы такое делать ?
M>1. функция funcA вызывает funcB. M>2. функция funcB, решает сколько ей нужно памяти, выделяет её в стеке и заполняет данными и возвращает указатель на выделенную память. M>3. сразу после возврата из funcB, мы сдвигаем регистр ESP(RSP), что-бы следующие вызовы не порушили эту память. Теперь внутри funcA мы можем безопастно использовать память выделенную в стеке funcB.
Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ?
Получается funcB вызывает функцию cb по ссылке или funcB завершается и потом уже funcA работает со стеком который остался от funcB ?
M>Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ?
Ни в каком не появилось, этот жирный тролль использовал GCC-шное расширение для VLA.
M>Получается funcB вызывает функцию cb по ссылке или funcB завершается и потом уже funcA работает со стеком который остался от funcB ?
M>Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ? M>Получается funcB вызывает функцию cb по ссылке или funcB завершается и потом уже funcA работает со стеком который остался от funcB ?
Посмотрел я код, который компилиет gcc 10.2. Он отдельно создал функцию (funcA()::{lambda(char*)#1}>} и её вызывает funcB. Соответсвенно лямда функция не может обращаться к переменным функции funcA. Ничего нового это не даёт, тоже самое если создать 3-ю функцию и её адрес передать в funcB.
Нужно было другое, работать в funcA со стеком, который остался от funcB после её завершения.
Здравствуйте, maks1180, Вы писали:
m> M>Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ? m> M>Получается funcB вызывает функцию cb по ссылке или funcB завершается и потом уже funcA работает со стеком который остался от funcB ?
m> Соответсвенно лямда функция не может обращаться к переменным функции funcA.
Почему не может? Есть же google: c++ lambda capture by reference
Здравствуйте, maks1180, Вы писали:
m>>> Соответсвенно лямда функция не может обращаться к переменным функции funcA. M>·>Почему не может? Есть же google: c++ lambda capture by reference M>Как вообще функция, может обращаться к переменным другой функции ?
по ссылке. ты в гугл-то ходил?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, σ, Вы писали:
M>>Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ?
σ>Ни в каком не появилось, этот жирный тролль использовал GCC-шное расширение для VLA.
Человек открыл для себя лямбда выражения, а ты ему про какие-то расширения.
Здравствуйте, σ, Вы писали:
M>>Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ?
σ>Ни в каком не появилось, этот жирный тролль использовал GCC-шное расширение для VLA.
Это опциональная часть C99: VLA
Компилятор вправе как реализовывать (GCC) так и не реализовывать (MSVC).
M>>>Спасибо! Это что-то новое для меня... Это в каком стандарте это появилось ?
σ>>Ни в каком не появилось, этот жирный тролль использовал GCC-шное расширение для VLA.
_NN>Это опциональная часть C99: VLA _NN>Компилятор вправе как реализовывать (GCC) так и не реализовывать (MSVC).
Ты, конечно, можешь напирать на то, что в цепепешном стандарте написано что он основан на стандарте C (C99 в C++11 и C++14), но ток вот что значит "основан" — ХЗ. Есть неопциональные части стандарта C, которые никакие цепепе-компиляторы не поддерживают. Так что это "основан" явно не про то, что C это подмножество C++, и не делает опциональные VLA из C99 такими же в цепепе. Сама дока GCC называет их поддержку в цепепе расширением.
Здравствуйте, _NN_, Вы писали: _NN>Использование VLA в C++ это да, нестандартно.
VLA, которые GCC поддерживает в С++ в качестве расширения — это не те VLA, которые тот же GCC поддерживает в C99. Это совершенно разные фичи, обладающие чисто косметическим сходством.