Printf текущий адрес в программе C

Хитрость заключалась в том, чтобы использовать GroupByUntil с Throttle на себе:

IObservable<List<Record>> Process(IObservable<Record> source, TimeSpan timeout)
{
    return source.GroupByUntil(x => x.Group, g => g.Throttle(timeout))
                 .SelectMany(x => x.ToList());
}
11
задан Nakilon 16 March 2014 в 01:08
поделиться

8 ответов

В gcc вы можете взять адрес метки с помощью оператора &&. Таким образом, вы можете сделать это:

int main() 
{
    int a=5, b= 6, c;

    sum:
        c = a+b;

    printf("Address of sum label in memory: %p", &&sum);
    return 0;
}

Результат && sum является целью инструкции перехода, которая была бы выполнена, если бы вы выполнили goto sum . Так что, хотя это правда, что в C / C ++ нет однозначного преобразования адреса в строку, вы все же можете сказать: «Дайте мне указатель на этот код».

23
ответ дан 3 December 2019 в 02:20
поделиться

Visual C ++ имеет встроенную функцию _ReturnAddress, которую можно использовать для получения здесь некоторой информации.

Например:

__declspec(noinline) void PrintCurrentAddress()
{
    printf("%p", __ReturnAddress);
}

Что даст вам адрес, близкий к выражению, которое вы ищете в. В случае некоторых оптимизаций, таких как складывание хвоста, это будет ненадежным.

6
ответ дан 3 December 2019 в 02:20
поделиться

Протестировано в Visual Studio 2008:

int addr;
__asm
{
    call _here
    _here: pop eax
    ; eax now holds the PC.
    mov [addr], eax
}

printf("%x\n", addr);

Благодарим за этот вопрос .

2
ответ дан 3 December 2019 в 02:20
поделиться

Here's a sketch of an alternative approach:

Assume that you haven't stripped debug symbols, and in particular you have the line number to address table that a source-level symbolic debugger needs in order to implement things like single step by source line, set a break point at a source line, and so forth.

Most tool chains use reasonably well documented debug data formats, and there are often helper libraries that implement most of the details.

Given that and some help from the preprocessor macro __LINE__ which evaluates to the current line number, it should be possible to write a function which looks up the address of any source line.

Advantages are that no assembly is required, portability can be achieved by calling on platform-specific debug information libraries, and it isn't necessary to directly manipulate the stack or use tricks that break the CPU pipeline.

A big disadvantage is that it will be slower than any approach based on directly reading the program counter.

1
ответ дан 3 December 2019 в 02:20
поделиться

Использование gcc на i386 или x86-64:

#include <stdio.h>

#define ADDRESS_HERE() ({ void *p; __asm__("1: mov 1b, %0" : "=r" (p)); p; })

int main(void) {
    printf("%p\n", ADDRESS_HERE());
    return 0;
}

Обратите внимание, что из-за наличия оптимизаций компилятора видимое положение выражения может не соответствовать его положению в исходном источнике.

Преимущество использования этого метода перед методом метки && foo в том, что он не меняет график потока управления функции. Он также не нарушает блок предсказания возврата, как подходы с использованием call :) С другой стороны, это очень сильно зависит от архитектуры ... и поскольку это не нарушает CFG, нет никакой гарантии, что переход к рассматриваемому адресу вообще будет иметь смысл.

0
ответ дан 3 December 2019 в 02:20
поделиться

Я не знаю подробностей, но есть должен быть способ сделать вызов функции, которая затем может сканировать стек возврата для адреса вызывающего, а затем скопировать и распечатать его.

0
ответ дан 3 December 2019 в 02:20
поделиться

For x86:

int test()
{
    __asm {
        mov eax, [esp]
    }
}


__declspec(noinline) int main() // or whatever noinline feature your compiler has
{
    int a = 5;
    int aftertest;

    aftertest = test()+3; // aftertest = disasms to 89 45 F8 mov dword ptr [a],eax.

    printf("%i", a+9);
    printf("%x", test());
    return 0;
}
1
ответ дан 3 December 2019 в 02:20
поделиться

If the compiler is any good this addition happens in registers and is never stored in memory, at least not in the way you are thinking. Actually a good compiler will see that your program does nothing, manipulating values within a function but never sending those values anywhere outside the function can result in no code.

If you were to:

c = a+b; printf("%u\n",c);

Then a good compiler will also never store that value C in memory it will stay in registers, although it depends on the processor as well. If for example compilers for that processor use the stack to pass variables to functions then the value for c will be computed using registers (a good compiler will see that C is always 11 and just assign it) and the value will be put on the stack while being sent to the printf function. Naturally the printf function may well need temporary storage in memory due to its complexity (cant fit everything it needs to do in registers).

Where I am heading is that there is no answer to your question. It is heavily dependent on the processor, compiler, etc. There is no generic answer. I have to wonder what the root of the question is, if you were hoping to probe with a debugger, then this is not the question to ask.

Bottom line, disassemble your program and look at it, for that compile on that day with those settings, you will be able to see where the compiler has placed intermediate values. Even if the compiler assigns a memory location for the variable that doesnt mean the program will ever store the variable in that location. It depends on optimizations.

0
ответ дан 3 December 2019 в 02:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: