В следующем коде get_func_name()
может быть системным вызовом, вызовом библиотеки или функцией, определенной мной самим. Без принятия каких-либо параметров, как я могу позволить get_func_name()
распечатать имя вызывающей функции, не используя информацию из стека?Как распечатать имя вызывающей функции, не глядя на стек?
Кроме того, помимо имени вызывающего, могу ли я распечатать что-либо в get_func_name()
, которое может однозначно идентифицировать вызывающего абонента?
void get_func_name(){
/*What magic goes here?*/
}
void func2(){
func3();
get_func_name(); /*Should print out "func2()"*/
}
void func1(){
func2();
get_func_name(); /*Should print out "func1()"*/
}
void main(){
func1();
get_func_name(); /*Should print out "main()"*/
}
Можете ли вы передать имя вызывающей функции в функцию 'get_func_name()'? Вы говорите «нет» ... тогда я не думаю, что вам есть возможность узнать вызывающую функцию, не проверяя фреймы стека (содержимое стека), чтобы узнать вызывающую функцию, и даже это очень сложно, особенно если функции встраиваемый. –
Не без проверки стека. Вам нужно будет найти обратный адрес в стеке. Это идентифицирует вызывающую функцию благодаря знанию диапазона адресов для каждой функции, что означает просмотр эзотерической, высокоплатформенной информации (которая может даже не присутствовать). Есть библиотеки, которые делают это, но они проверяют стек. Один (плохой) способ сделать это - иметь преамбулу и postamble для каждой функции, которая подталкивает свое имя ('__func__') к стеку указателей (контролируемых пользователем); то вы можете найти вызывающую иерархию. Боль заключается в том, что никто не ошибается. –
@ Джонатан. Даже проверка стека не помогла бы; Нет никакой гарантии, что строка, содержащая имя вызывающей функции, существует даже в двоичном (например, статические функции, которые не образуют внешний интерфейс и имя которых, таким образом, не должно записываться как точка входа). Эти же функции могут быть встроены в собственные вызовы, поэтому обратный адрес будет указывать на вызывающего абонента. Наконец, если вызывающий абонент является частью цепочки вызовов, обратный указатель указывает на функцию, которая инициировала цепочку; Это может быть * очень * далеким от непосредственной функции вызова. –