Visual Studio 2010’s vreemde “waarschuwing LNK4042”

Ik ben zojuist (vrijwel nauwelijks) op mijn hoofd geslagen door een niet-triviale waarschuwing van Visual Studio 2010 (C++).

De compilatie gaf de volgende output:

1 Debug\is.obj : waarschuwing LNK4042: object meer dan eens opgegeven; extra’s genegeerd
1 Debug\make.obj : waarschuwing LNK4042: object meer dan eens opgegeven; extra’s genegeerd
1 Debug\view.obj : waarschuwing LNK4042: object meer dan eens opgegeven; extra’s genegeerd
1 identiteit.obj: fout LNK2019: onopgelost extern symbool void __cdecl
test::identity::view(void)
(?view@identity@test@@YAXXZ) waarnaar wordt verwezen in functie void __cdecl test::identity::identity(void)(?identity @0test@@YAXXZ)
1 identiteit.obj: fout LNK2019: onopgelost extern symbool void __cdecl test::identity::make(void)(?make@identity@test@@YAXXZ) waarnaar wordt verwezen in functie void __cdecl test::identity::identity(void)(?identity@0test@@YAXXZ)
1 range.obj: fout LNK2019: onopgelost extern symbool void __cdecl test::range::is(void)(?is@range@test@@YAXXZ) waarnaar wordt verwezen in functie void __cdecl test::range::range(void)(?range@0test@@YAXXZ)

Linkerfouten zijn altijd lastig om te debuggen… maar er waren onopgeloste verwijzingen, en dus heb ik het gecontroleerd… maar de bron is goed gevormd… en uiteindelijk drong het tot me door:

Mijn mappenhiërarchie ziet er als volgt uit:

src/
  identity/
    is.cpp
    make.cpp
    view.cpp
  range/
    is.cpp
    make.cpp
    view.cpp

en dat geldt ook voor de hiërarchie in de oplossing (ik stel het altijd zo in dat het de “echte” mapstructuur nabootst).

En de diagnostische uitgangen:

Debug\is.obj
Debug\make.obj
Debug\view.obj

Samen met een waarschuwing die zegt dat de .objtwee keer is doorgegeven aan de linker en dat deze wordt genegeerd.

Zoek niet meer: ​​Visual heeft mijn mappenhiërarchie netjes afgevlakt en kan daarom de broncode niet netjes compileren.

Op dit moment denk ik er gewoon aan om de bestanden te hernoemen, dat zou het probleem moeten dekken…

… maar is er een manier om Visual Studio de bestandshiërarchie NIET te laten afvlakken?


Antwoord 1, autoriteit 100%

Ik had een soortgelijk probleem met linkerwaarschuwing LNK4042: object meer dan eens opgegeven; extra’s genegeerd. In mijn geval probeerde Visual Studio zowel header- als bronbestanden met dezelfde naam te compileren – MyClass.hen MyClass.cpp. Het gebeurde omdat ik het bestand .cpphernoemde naar .hen Visual Studio in de war raakte. Ik merkte het probleem op door naar de compilerlogboeken te kijken in de map Debug. Om dit op te lossen, verwijdert u het bestand .huit het project en voegt u het opnieuw toe.


Antwoord 2, autoriteit 65%

Ik wilde gewoon crossposten wat volgens mij het antwoord is, als je de eigenschappen voor het hele project opent en de waarde wijzigt onder C/C++ -> Output Files -> "Object File Name"moet de volgende zijn:

$(IntDir)/%(RelatieveDir)/

Onder VS 2010 denk ik dat dit alle objectbestanden ondubbelzinnig zal maken (omdat ik geloof dat Windows je onder geen enkele gekke omstandigheden twee bestanden met dezelfde namen in dezelfde map zal laten hebben). Bekijk ook de details hier.


Antwoord 3, autoriteit 5%

Klik met de rechtermuisknop op het .cpp-bestand in het Solution Explorer-venster, Eigenschappen, C/C++, Uitvoerbestanden, Objectbestandsnaam instelling. De standaardwaarde is $(IntDir)\, dat is wat de afvlakking doet. Alle .obj-bestanden gaan naar $(IntDir), de map “Debug” in de debug-configuratie.

U kunt de instelling wijzigen, bijvoorbeeld $(IntDir)\is2.obj. Of selecteer alle bestanden uit één groep (gebruik Shift+klik) en verander de instelling in bijvoorbeeld $(IntDir)\identity\

Of je kunt de .cpp-bestandsnaam wijzigen zodat .obj-bestanden elkaar niet overschrijven. Het is een beetje vreemd om bestanden met exact dezelfde naam in twee mappen te hebben.

Of u kunt meerdere projecten maken, bijvoorbeeld .lib-projecten maken voor de bestanden in identiteit en bereik. Vaak gedaan in makefile-projecten bijvoorbeeld. Dat maakt het beheer van de compileer- en koppelingsinstellingen echter een stuk lastiger, tenzij u projecteigenschappenbladen gebruikt.


Antwoord 4, autoriteit 5%

Klik met de rechtermuisknop op het headerbestand -> Eigenschap -> ItemType (selecteer C/C++ Header). Doe hetzelfde met het Cpp-bestand, maar selecteer C/C++ Compiler (het is werk voor mij)


Antwoord 5, autoriteit 3%

Ik gebruik $(IntDir)\%(Directory)\ onder C/C++ -> Uitvoerbestanden -> “Objectbestandsnaam”.


Antwoord 6, autoriteit 3%

Als alternatief voor het verwijderen en het maken van een nieuw bestand kunt u de instellingen voor compileren/opnemen wijzigen.

Ga naar je project.vcxprojbestand, open het met een editor, zoek de html-achtige regel <ItemGroup>.

Het zou er ongeveer zo uit moeten zien:

<ItemGroup>
<ClCompile Include="implementation.cpp" />
</ItemGroup>

en

<ItemGroup>
<ClInclude Include="declaration.hpp" />
</ItemGroup>`

Ervan uitgaande dat uw implementatiebestanden .cpp zijn en uw declaraties .hpp. Zorg ervoor dat al uw implementatiebestanden tussen de eerste sectie staan ​​als je er meer dan één hebt en ook voor de tweede sectie voor meerdere aangiftebestanden.


Antwoord 7, autoriteit 2%

Ik had dit probleem met stdafx.cpp. Op de een of andere manier werd stdafx.cpp gedupliceerd, dus er was een tweede StdAfx.cpp (let op het andere geval).

Nadat ik StdAfx.cpp had verwijderd, werkte alles goed!

VS 2010 gebruiken


Antwoord 8

Ik had in hetzelfde project .cen .cppbestanden met dezelfde bestandsnamen. De bestanden stonden overal in mappen en de oplossingen van anderen zorgden voor een puinhoop en maphel (in mijn geval). Zelfs Releasebuilds zouden Debugbuilds overschrijven!

Een goede (niet perfecte) oplossing zou zijn om $(ParentName) te gebruiken, maar om de een of andere reden is het verwijderd uit latere versies van Visual Studio (2015+).

Wat ik nu met succes gebruik is:
$(IntDir)%(Bestandsnaam)%(Extensie).obj

die op zijn minst de door .cgebouwde objectbestanden scheidt van .cpp.


Antwoord 9

Ik wil graag wijzen op een mogelijke reden waarom het ItemTypevan een .h filezou veranderen van de C/C++ headernaar C/C++ compiler:

  1. Klik in het venster Solution Explorervan VS (2019 hier) met de rechtermuisknop op de projectnaam en kies Add -> New Item;
  2. Selecteer de sjabloon C++ File (.cpp), maar typ something.hin het invoerveld voor de naam en klik vervolgens op OKom toe te voegen het;
  3. Dan krijg je de LNK4042-waarschuwing als het something.h-bestand wordt opgenomen in meer dan één .cpp-bestand.

Antwoord 10

Ik heb zojuist een soortgelijke foutmelding overwonnen, en nog veel meer met de onderstaande procedure. Symptoom: één linkerfout voor elke aanroep van elke functie gedefinieerd in een bepaalde kop, plus één aan het einde van de uitvoer voor elke functie die in de kop is gedefinieerd.

Toen herinnerde ik me dat toen ik deze header oorspronkelijk had gemaakt, ik per ongeluk “add->new item->c++ file” had geselecteerd en hoewel ik het ‘whatever.h’ noemde, lijkt het alsof Visual Studio ze allebei heeft overwogen dezelfde soorten bestanden vanwege de onjuiste actie die ik gebruikte om er een toe te voegen.Het onderzoeken van de uitvoerlogboeken van de build maakte dit duidelijk.

OPLOSSING (Gebruik van VS Community 2019)

  1. Maak eerst een back-up van het project (voor de zekerheid).
  2. Klik met de rechtermuisknop op het aanstootgevende headerbestand en selecteer “Uitsluiten van project” (hierdoor worden ze niet verwijderd; het VS-project negeert ze gewoon).
  3. Doe hetzelfde voor het overeenkomende .c- of .cpp-bestand.
  4. Bouw->Reinig op project
  5. Doe Bouw->Herbouw op project
    — er zullen natuurlijk fouten zijn —
  6. Klik met de rechtermuisknop op Header Files->Add->Existing Item en selecteer vervolgens het .h-bestand
  7. Klik met de rechtermuisknop op Bronbestanden->Add->Bestaand item en selecteer het .c- of .cpp-bestand
  8. Doe bouwen->herbouwen op project.

Dit heeft het voor mij volledig opgeruimd en me verlost van veel irritante linker-fouten, waaronder LNK4042 uit de titel van deze vraag.

Other episodes