2

I have created a sample c++ project under Visual Studio 2010 with following files.

A.h

#ifndef A_H
#define A_H

#include <iostream>

void foo();

#endif

A.cpp

#include "A.h"

void foo()
{
    int a = 1;
}

main.cpp

#include "A.h"

int main(int argc, char* argv[])
{
    foo();    

    return 0;
}

I am getting the following output after build:

1>------ Build started: Project: opengl_test, Configuration: Debug Win32 ------

1> main.cpp

1> A.h

1> A.cpp

1> Generating Code...

1>Debug\A.obj : warning LNK4042: object specified more than once; extras ignored

1>main.obj : error LNK2019: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ) referenced in function _main

1>C:\Users\alp\Projects\Test Samples\opengl_test\Debug\opengl_test.exe : fatal error LNK1120: 1 unresolved externals

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

What is the reason for this error?

Alp
  • 553
  • 11
  • 30
  • possible duplicate of [Visual Studio 2010's strange "warning LNK4042"](http://stackoverflow.com/questions/3695174/visual-studio-2010s-strange-warning-lnk4042) – Cody Gray - on strike Jan 25 '12 at 03:15
  • For what it's worth, I **cannot** repro this in a new, empty project in VS 2010. I just added your 3 code files (`A.h`, `A.cpp`, and `main.cpp`) and then compiled. Works fine, no errors. So the question is, what's different about your setup than mine (and what you've described in the question)? – Cody Gray - on strike Jan 25 '12 at 03:19
  • @CodyGray I created a new solution and added these files to the project and now builds without any errors or warnings. The thing is the project was first referencing opengl/glut functions and at some point visual studio started giving me this LNK2019 error and it wasn't giving it all the time as I described here http://stackoverflow.com/questions/8996385/c-unresolved-external-symbol-error-after-clean . Then it started giving it always. So I converted the project into this simple form and it kept giving the error. I don't know what caused the configuration difference between the 2 projects. – Alp Jan 25 '12 at 03:34
  • So perhaps [this question](http://stackoverflow.com/questions/3695174/visual-studio-2010s-strange-warning-lnk4042) is relevant. Does the OpenGL libraries by chance contain a file with the name `A` that could be messing the linker up if/when it flattens the hierarchy? – Cody Gray - on strike Jan 25 '12 at 03:35
  • In that question poster has a directory structure for the files. In my project I didn't have any directory structure, every file was in the same folder with the .vcxproj file. I tried that solution but it didn't resolve the warning. The file's name wasn't A before(it was Listing2_2 which I am pretty confident don't exist in opengl) and I changed it to A to make it simple for the post – Alp Jan 25 '12 at 03:42

4 Answers4

3

I think what happened is that A.h was in the Source group of the project rather than the Header group, so it was compiled as if it were a .cpp. Since both A.cpp and A.h will generate an object file A.obj, the last one to compile is the only one that got linked. I believe the last one compiled was A.h, which didn't have an implementation of foo(), thus the linker couldn't find it.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • This seems more reasonable than my explanation. – Alp Jan 27 '12 at 00:18
  • However, the error exists after I clean the project. Shouldn't visual studio delete all obj files and compile with new files? – Alp Jan 27 '12 at 00:24
  • @AlpHancioglu, cleaning the project is a necessary step - but so is moving `A.h` out of the `Sources` group. – Mark Ransom Jan 27 '12 at 00:31
0

EDIT: Nevermind the original answer (below), I believe what you're looking for may be here: Visual Studio 2010's strange "warning LNK4042"

Original answer (not the problem, but maybe sound advice?): Your header should have guards around it, otherwise it will be defined each time it is called, and cause redefinitions.

#ifndef A_H
#define A_H

#include <iostream>

void foo();

#endif //A_H
Community
  • 1
  • 1
Nic Foster
  • 2,864
  • 1
  • 27
  • 45
  • That doesn't look like a definition though, just a prototype. Is this yet another case of "C++ doesn't work like C" ? – sarnold Jan 25 '12 at 02:08
  • Although this is definitely a good advise in general, it does not look applicable to this question, as the OP is not including a.h in the same compilation unit. – Sergey Kalinichenko Jan 25 '12 at 02:10
  • @AlpHancioglu: I've added more information, maybe you're experiencing a naming conflict. – Nic Foster Jan 25 '12 at 16:00
0

First, you need to include "stdafx.h" in your "a.cpp" file before the line for including "a.h".

Second, it is better you add "a.h" into your project "Header Files" and add "a.cpp" into your "Source Files".

Then it will be compiled without error! Good luck.

BTW, the reason to include "stdafx.h" is that by default the project use pre-compiled headers that is why the compiler looks for "stdafx.h".

If you want, you can disable the "precompiled Header" then you don't need "stdafx.h" and everything will be fine.

CS Pei
  • 10,869
  • 1
  • 27
  • 46
  • Why do I need to include stdafx.h? This is not a visual c++ application and I am not using any MFC classes, or Windows API functions or targeting .NET. This is a simple native c++ application. Header file is under the Header Files section and cpp files are under the Source Files section like you said. – Alp Jan 25 '12 at 02:57
  • @Alp: `stdafx.h` is the default name for the precompiled header. It has nothing inherently to do with any of the technologies that you mentioned. But precompiled headers are *optional* (though enabled by default), and you can name your precompiled header anything you want. So yes, this part of the answer is likely wrong. But your understanding of `stdafx.h` is also wrong. :-) – Cody Gray - on strike Jan 25 '12 at 03:14
  • hi,all. you need to try it and to see if am wrong or not. Actually I didn't think I should include "stdafx.h" either. But the compiler complained and suggested that I should include that and I did. Bingo, it works! – CS Pei Jan 25 '12 at 14:46
  • Yes, you must include it if you have precompiled headers turned on. They're on by default. But you can turn them off, and you can change the name of the precompiled header that the compiler looks for. It doesn't have to be called `stdafx.h`. This is like saying you have to include `windows.h`. Well, yes, if you want to call functions from the Windows API, but not if you aren't using the functions it contains. – Cody Gray - on strike Jan 26 '12 at 06:44
0

The code works when I created a new project. I am not sure but the reason of the error might be that I added the folder "C:\Program Files\Microsoft SDKs\Windows\v7.1\Include" to the included directories at the project settings and Visual Studio already included the folder "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include"(which is for the 32 bit programs) by default. So there might be a clash because of that. I added the opengl header files only to the Program Files(x86) include folder, removed the include for 64 bit Program Files folder and the opengl code seems to be working now.

Alp
  • 553
  • 11
  • 30