Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ redefinition of variable, global namespace polluted and I don't know why

so I think I've done something really stupid and I just can't figure this out. The following program is causing me a lot of pain:

#include <iostream>
int time = 0;
int main(int argc, char **argv) {
    std::cout << "hi" << std::endl;
    return 0;
}

My compile string is: clang++ -std=c++1y --verbose -stdlib=libc++ main.cpp -o main. The redefinition error is /usr/include/time.h:116:8: note: previous definition is here and the --verbose shows me this as the include path order:

Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
 "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.10.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 241.9 -v -resource-dir /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.0 -stdlib=libc++ -std=c++1y -fdeprecated-macro -fdebug-compilation-dir /Users/aliak/dev/atom/sim -ferror-limit 19 -fmessage-length 0 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-slp -o /var/folders/r_/pmd7rtcd4h35dqsf496nyzsh0000gn/T/main-d500bd.o -x c++ /Users/aliak/dev/atom/sim/main.cpp
clang -cc1 version 6.0 based upon LLVM 3.5svn default target x86_64-apple-darwin14.1.0
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1
 /usr/local/include
 /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.0/include
 /Library/Developer/CommandLineTools/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)

I just can't figure out what's wrong. If I add in -nostdinc++ to the command line args to clang and then remove the iostream include, but keep the time var, it's all ok. Which I guess means the iostream is including time.h. But I am quite confused, should it not include ctime instead of time.h, which would wrap everything in the std namespace?

I've tried deleting xcode and reinstalling as well.

Update:

The comment from Mats made me do a little bit more snooping. So passing in -H to clang++ prints out the header tree. And it turns out that pthread.h is the one actually including time.h. But ctime also actually includes time.h. And this seems according to the standard because: "In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations"

like image 542
aliak Avatar asked Feb 11 '15 23:02

aliak


1 Answers

time() is a function in standard C, which means that it's living outside a namespace so that "old" C code can be compiled with C++ compilers without having lots of using namespace std thrown in all over the place.

The header time.h is apparently included when you include <iostream>, which is why you get a reference to that.

Either don't use that name, or add namespace MyName { int time; }; and then use MyName::time when you want to refer to your variable.

[I don't know the exact place, but I beleive the C++ standard states that "existing standard library functions may or may not exist outside of the std:: namespace when you include for example <ctime> - the actual implementation of <ctime> does almost certainly include regular <time.h> somewhere.]

For example in the g++ 4.9.2 headers on my linux box:

....
#pragma GCC system_header

#include <bits/c++config.h>
#include <time.h>

#ifndef _GLIBCXX_CTIME
#define _GLIBCXX_CTIME 1

 ...     
namespace std
{
  ...
  using ::time;
  ...
} // namespace

The one in libcxx looks almost identical.

like image 143
Mats Petersson Avatar answered Nov 11 '22 00:11

Mats Petersson