локальная переменная с конфликтующим именем во встроенной функции - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь изучить тонкости inline. Для этого я создал эту маленькую программу. Я определил встроенную функцию, которая имеет переменную automati c с тем же именем, что и глобально определенная переменная. Убедившись, что моя функция помечена static (для соответствия стандарту C99), я изучаю исполняемый файл, созданный с помощью objdump. Но сначала, вот моя программа

#include <stdio.h>
#include <stdlib.h>

int AAAABBBB = 5; //global scope

#define DOINLINE$

#ifdef DOINLINE
static inline void  __attribute__((always_inline)) myfunc() {
#else
void myfunc() {
#endif
    static int AAAABBBB = 6;
    printf("global is now %d\n", AAAABBBB);
}

int main() {
    printf("global is %d\n", AAAABBBB);
    myfunc();
    printf("global is now %d\n", AAAABBBB);
    return 0;
}

Эта функция работает, как и ожидалось, и между этими, казалось бы, конфликтующими именами возникает конфликт нет . Однако, глядя на объектный дамп исполняемого файла (а также объектный файл), я вижу, что компилятор действительно выполнил мой запрос, и нет отдельного раздела для myfunc.

Вот вставка objdump . Я уверен, что локальная переменная внутри myfunc похоронена где-то в нем, но не может понять, где она находится.

Примечание

Объявление локальной переменной функции как неустановленной c, кажется, не имеет никакого отношения.

1 Ответ

2 голосов
/ 19 марта 2020

AAAABBBB, определенный внутри myfunc, не появляется в объектном файле, потому что компилятор его оптимизировал. Это можно увидеть в разборке main, где это код, полученный в результате встраивания myfunc:

    1154:   be 06 00 00 00          mov    esi,0x6
    1159:   48 8d 3d b2 0e 00 00    lea    rdi,[rip+0xeb2]        # 2012 
    1160:   b8 00 00 00 00          mov    eax,0x0
    1165:   e8 c6 fe ff ff          call   1030 

Здесь мы видим, что компилятор просто передал 6 непосредственно в printf; это никогда не было сохранено в памяти. AAAABBBB в myfunc не существует в объектном файле, кроме этого.

Можно задаться вопросом, как объект stati c, который должен существовать для всего выполнения программы, может быть удалены компилятором во время оптимизации. Стандарт C говорит, что, по сути, реализация C может оптимизировать программу любым способом, который не изменяет наблюдаемое поведение, а именно:

  • Доступ к изменчивым объектам оценивается строго.
  • Когда программа завершается, данные, записанные в файлы, соответствуют определенным.
  • Взаимодействия с интерактивными устройствами, такими как терминал, являются такими, как указано в разделе «Файлы».

Поскольку запись данных для статического c (но не энергозависимого) объекта в память не является частью наблюдаемого поведения (а наличие вообще памяти для него вообще не является наблюдаемым поведением), компилятор бесплатно удалить его во время оптимизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...