C++ - linkage
От: wander  
Дата: 01.03.14 14:40
Оценка:
Доброго здравия вам

Есть вот такой код (два файла):
a.cpp
#include <iostream>

namespace
{
    int a = 0;
}

int main()
{
    extern int a;

    std::cout << a   << std::endl;
    std::cout << ::a << std::endl;

    return 0;
}

b.cpp
int a = 1;

На GCC 4.7.2 я получаю вывод 1, 0
На VS 2012 получаю 0, 0.

Студия получается изменяет linkage переменной внутри анонимного namespace. Правильно ли это?
Читал стандарт и не нашел явных запретов на это, но и подтверждений такому поведению тоже (может быть что-то упустил).
Спасибо.
Re: C++ - linkage
От: uzhas Ниоткуда  
Дата: 03.03.14 07:22
Оценка:
Здравствуйте, wander, Вы писали:

W>Студия получается изменяет linkage переменной внутри анонимного namespace.

откуда такие выводы? я бы дополнительно распечатал адреса переменных вместе со значениями, ибо подозреваю, что просто компиляторы цепляются за разные переменные, то есть для студии a и ::a ссылаются на одну переменную
Re[2]: C++ - linkage
От: Кодт Россия  
Дата: 03.03.14 09:24
Оценка: 6 (1)
Здравствуйте, uzhas, Вы писали:

W>>Студия получается изменяет linkage переменной внутри анонимного namespace.

U>откуда такие выводы? я бы дополнительно распечатал адреса переменных вместе со значениями, ибо подозреваю, что просто компиляторы цепляются за разные переменные, то есть для студии a и ::a ссылаются на одну переменную

Именно так. Только это шутки линкера.
namespace
{
    int a = 0;
}
int a = 123; // * если перенести определение сюда из строки ***

template<int* P> struct foo {};

int main()
{
    extern int a; // то компиляторы ругаются на неоднозначность здесь
    bool e = ((void*)&a == (void*)&::a); // и здесь

    foo<&a> f1;
    foo<&::a> f2;
    f1 = f2; // ** иначе, компиляторы ругаются на несоответствие типов foo<&`anonymous-namespace'::a> и foo<&::a>

    std::cout << std::boolalpha << e << std::endl;

    return 0;
}

int a = 123; // ***

Но если * и ** закомментировать, то VC (2010, 2012) напишут true, а gcc — false.
Перекуём баги на фичи!
Re[2]: C++ - linkage
От: wander  
Дата: 03.03.14 11:17
Оценка:
Здравствуйте, uzhas, Вы писали:

U>откуда такие выводы?


Ну ладно, хорошо, выводы неправильные, Кодт успешно это доказал.
Но вопрос-то исходный остался, куда в стандарте смотреть?
Re[3]: C++ - linkage
От: Кодт Россия  
Дата: 04.03.14 14:31
Оценка: 9 (1)
Здравствуйте, wander, Вы писали:

W>Ну ладно, хорошо, выводы неправильные, Кодт успешно это доказал.

W>Но вопрос-то исходный остался, куда в стандарте смотреть?

Лень качать стандарт, а гугл навёл на SO:
http://stackoverflow.com/questions/4181059/linkage-of-symbols-within-anonymous-namespace-within-a-regular-namespace
C++11 (draft N3337) §3.5/4
An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage.

Так что гусь и 2012 работают правильно, и даже парсер 2010 работает правильно...


Сейчас посмотрел на ассемблер — это косячит кодогенератор.
namespace
{
    int alfabravo = 7;
}

int main()
{
    extern int alfabravo;
    return alfabravo - ::alfabravo;
}

int alfabravo = 5;

получается вот что
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01 

include listing.inc

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

;***** хоть связывание и внутреннее, но линкеру видны оба символа

PUBLIC    ?alfabravo@?A0xf80c3d98@@3HA            ; `anonymous namespace`::alfabravo
PUBLIC    ?alfabravo@@3HA                    ; alfabravo

;***** переменные действительно разные, находятся по разным адресам и принимают разные значения

_DATA    SEGMENT
?alfabravo@?A0xf80c3d98@@3HA DD 07H            ; `anonymous namespace`::alfabravo
?alfabravo@@3HA DD 05H                    ; alfabravo
_DATA    ENDS

PUBLIC    main
; Function compile flags: /Odtp
; File c:\workspace\other\xz.cpp
_TEXT    SEGMENT
main    PROC

; 8    :     extern int alfabravo;
; 9    :     return alfabravo - ::alfabravo;

  ;***** внезапно!
  00000    8b 05 00 00 00
    00         mov     eax, DWORD PTR ?alfabravo@?A0xf80c3d98@@3HA ; `anonymous namespace`::alfabravo

  00006    8b 0d 00 00 00
    00         mov     ecx, DWORD PTR ?alfabravo@?A0xf80c3d98@@3HA ; `anonymous namespace`::alfabravo
  0000c    2b c8         sub     ecx, eax
  0000e    8b c1         mov     eax, ecx

; 10   : }

  00010    c3         ret     0
main    ENDP
_TEXT    ENDS
END
Перекуём баги на фичи!
Re[4]: C++ - linkage
От: wander  
Дата: 04.03.14 21:07
Оценка:
Здравствуйте, Кодт, спасибо — понятно все.
Не подумал я чего-то, в этом случае, в асм лезть. Первым делом грешить начал, что или студия стандарт опять недособлюла, либо я совсем слепой стал и важное что пропустил.
А ссылку со стандарта эту я знаю. И ведь extern int a в области видимости функции должен был скрыть глобальное имя a. Оттого и подумал, что студия linkage у переменной в анонимном неймспейсе поменяла.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.