Как получить доступ к начальному адресу кучи и базовому адресу кучи в функции c

Для моей собственной реализации malloc с динамическим распределением памяти я хочу получить доступ к базовому адресу кучи и адресу ограничения кучи во время выполнения. Я знаю, что они экспортируются как глобальные в моем файле startup.s. Как я могу получить доступ к этим адресам? Целевая платформа - ARM Cortex-M4 с GCC.

Символы, объявленные с помощью .globl, известны компоновщику и должны быть доступны с помощью символа extern в коде c. Но с помощью этого метода я получаю значения, которые отличаются от значений в сгенерированном файле .map.

Вот символы кучи, определенные в файле startup.s:

#ifdef __HEAP_SIZE
    .equ        Heap_Size, __HEAP_SIZE
#else
    .equ        Heap_Size, 0x00000C00
#endif
    .globl      __HeapBase
    .globl      __HeapLimit
__HeapBase:
    .if Heap_Size
    .space      Heap_Size
    .endif
    .size       __HeapBase, . - __HeapBase
__HeapLimit:
    .size       __HeapLimit, . - __HeapLimit

    .section    .vectors
    .align      2
    .globl      __Vectors

Вот мой доступ к моей функции c:

extern volatile __HeapBase;
extern volatile __HeapLimit;

static void heaptest(void) {
    uint32_t limit;
    uint32_t base;

    base = __HeapBase;
    limit = __HeapLimit;
}

Отлаживая этот код, я получаю адреса, отличные от указанных в сгенерированном файле .map:

.heap           0x200317a0    0x40000
                0x200317a0                __HeapBase = .
...
                0x200717a0                __HeapLimit = .
...

Поэтому я ожидаю, что результат будет 0x200317a0 для __HeapBase и 0x200717a0 для __HeapLimit, но фактические результаты, которые я получаю, 0xf377aaa2 и 0xac69254.


person D. Smith    schedule 29.08.2019    source источник
comment
Как вы это компилируете, связываете и запускаете? Добавьте остальной необходимый код, чтобы получить минимальный и воспроизводимый пример (акцент на воспроизводимый ).   -  person Marco Bonelli    schedule 29.08.2019


Ответы (2)


Экспортированные символы являются адресами, но компилятор C разыменует их за вас. Чтобы вернуть адрес, нужно применить оператор адресации &, то есть void* base = &__HeapBase; должен работать. Как написано, вы фактически извлекаете первый элемент из кучи.

person Jester    schedule 29.08.2019

Объявите их как extern char __HeapBase[];, потому что в C имя объекта массива преобразуется в указатель, а имена других объектов неявно разыменовываются.

Возможно также использовать #define HEAPBASE ((void*)__HeapBase), чтобы было удобно использовать имя. Или переведите его в (uintptr_t) или что-нибудь еще.

Было бы не так хорошо иметь отдельный глобальный void *base = &__HeapBase;: base не является значением константы времени компиляции, потому что оно даже не объявлено как const. Код, который его использует, должен будет загрузить указатель из статического хранилища вместо того, чтобы иметь постоянный адрес времени компоновки, который они могут использовать напрямую.

person Peter Cordes    schedule 29.08.2019