повторное определение подставляемой функции

Xcode 8.3.1 - Swift 3

Это принятый ответ paulvs, преобразованный в Swift 3:

let myGroup = DispatchGroup()

override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0 ..< 5 {
        myGroup.enter()
        Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { response in
            print("Finished request \(i)")
            myGroup.leave()
        }
    }

    myGroup.notify(queue: DispatchQueue.main, execute: {
        print("Finished all requests.")
    })
}
25
задан Michael Mrozek 27 April 2010 в 15:32
поделиться

6 ответов

Ошибка компиляции вызвана тем, что в функции func1 () есть дублированное определение;

Поскольку func1 () определяется с использованием extern inline, он создаст внешнее определение.

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

Однако, func2 () и func3 () не создают внешнего определения, следовательно, нет ошибки переопределения.

Вы можете посмотреть здесь http://www.greenend.org.uk/rjk/2003/03/inline.html .

Кроме того, обратите внимание, что c ++ и c по-разному относятся к встроенным функциям, и даже в c разные стандарты (c89 и c99) по-разному относятся к встроенным функциям.

3
ответ дан SHH 28 November 2019 в 21:54
поделиться

Этот ответ состоит из следующих разделов:

  1. Как воспроизвести проблему duplicate definition of inline function - func3 и почему.
  2. Почему определение func3 является дубликатом вместо func1.
  3. Почему он компилируется с использованием g++

Как создать дублирующее определение встроенной функции - проблема func3

Эта проблема может быть успешно воспроизведена

  1. Переименовать tran.cpp в tran.c
  2. Компилировать с gcc -o main main.c tran.c

@ K71993 фактически компилируется с использованием старой встроенной семантики gnu89, которая отличается от C99. Причиной переименования tran.cpp в tran.c является указание драйверу gcc трактовать его как источник C вместо источника C++.


Почему определение func3 является дубликатом вместо func1.

Встроенная семантика GNU 89

Следующий текст процитирован из Документ GCC: встроенная функция выполняется так же быстро, как макрос , объясняет, почему func3 является дублирующим определением вместо func1 ], поскольку func3 (вместо func1) является внешне видимым символом (во встроенной семантике GNU89)

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

Если вы укажете как inline, так и extern в определении функции , то это определение используется только для встраивания. Ни в коем случае функция не компилируется сама по себе, даже если вы явно ссылаетесь на ее адрес. Такой адрес становится внешней ссылкой, как если бы вы только объявили функцию и не определили ее.

Встроенная семантика C99

Если компилируется со стандартом C99, т.е. gcc -o main main.c tran.c -std=c99, компоновщик будет жаловаться, что определение func1 является дубликатом из-за причины, по которой extern inline в C99 - это внешнее определение, упомянутое в других постах и ​​комментариях.

Также см. этот отличный ответ о семантических различиях между GNU89 inline и C99 inline.

Почему он компилируется с использованием g++.

При компиляции с g++ исходная программа рассматривается как C++ источник. Поскольку func1, func2 и func3 определены в нескольких единицах перевода, а их определения различны, одно правило определения для C ++ нарушается. Поскольку компилятору не требуется генерировать сообщение с достоинством, когда определения охватывают несколько единиц перевода, поведение не определено.

13
ответ дан Community 28 November 2019 в 21:54
поделиться

Ваш код недопустим с точки зрения C ++, поскольку он явно нарушает Правило Единого Определения. Единственная причина, по которой вам удалось скомпилировать его с помощью компилятора C ++, - это свободная проверка ошибок в вашем компиляторе C ++ (это одна из тех частей ODR, где «диагностика не требуется»).

Ваш код не является допустимым C, поскольку он обеспечивает дублирование внешнего определения функции func1. Заметим, что с точки зрения C проблематично func1, а не func3. Там нет ничего формально не так с вашим func3. Ваш func2 также в порядке, если два определения никогда не «встречаются» друг с другом в одной и той же единице перевода.

Одной из возможных причин, по которой вы можете получить другой диагностический отчет от вашего компилятора, является то, что ваш компилятор C может поддерживать inline функции некоторым нестандартным для компилятора способом (либо компилятором до C99, либо запуском современного компилятора). в нестандартном «традиционном» режиме).

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

1
ответ дан AnT 28 November 2019 в 21:54
поделиться

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

  • inline.h имеет extern inline int func1(void) Это не имеет никакого смысла.
  • main.h имеет #define <stdio.h> Я думаю, что вы имели в виду include вместо.

Как только я исправил их и скомпилировал с помощью gcc, он скомпилировался нормально, и я получил следующий вывод

5
6
7

Когда я скомпилировал с g ++, я получил такой вывод:

5
6
700

Это происходит потому, что func3 () не является статическим в inline.h

2
ответ дан JayM 28 November 2019 в 21:54
поделиться

Ошибка компиляции, которую вы видите, на самом деле является ошибкой компоновщика.

gcc и g ++ трактуют static inline немного по-другому. inline была сначала частью C ++, а затем превращена в расширение для многих компиляторов C, прежде чем была добавлена ​​в стандарт C. Стандартная семантика может отличаться, но это могут быть просто разные реализации.

Это также может иметь какое-то отношение к каким-то безумным вещам, которые происходят с кодом C ++, который избавляется от дублирующихся шаблонов, ловящих другие дублирующиеся вещи.

0
ответ дан nategoose 28 November 2019 в 21:54
поделиться

В основном Inline - поздняя запись в GCC (я имею в виду c-компилятор). «[....] Встроенное определение не предоставляет внешнего определения для функции и не запрещает внешнее определение в другой единице перевода. Встроенное определение предоставляет альтернативу внешнему определению, которое переводчик может использовать для реализации любого вызов функции в том же модуле перевода. Не определено, использует ли вызов функции встроенное определение или внешнее определение. " - ISO 9899: 1999 (E), стандарт C99, раздел 6.7.4

0
ответ дан haramohan sahu 28 November 2019 в 21:54
поделиться
Другие вопросы по тегам:

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