[gelöst] Visual C++ 2015: /ENTRY und C Runtime

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8239
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[gelöst] Visual C++ 2015: /ENTRY und C Runtime

Beitrag von Krishty »

Weil das Gejammer über Visual Studio 2015 nicht abreißt … ich sehe hier sonderbares Verhalten mit selber definiertem Einsprungspunkt:
  • Kein selber definierter Einsprungspunkt; keine CRT-Funktionen überschrieben (Standardfall): Funktioniert.
  • Kein selber definierter Einsprungspunkt, aber CRT-Funktionen überschrieben:
    error LNK2005: atexit already defined in framework.obj
    Die vorherigen Compiler-Versionen haben das zuerst definerte Symbol (meins) genommen und die CRT-Symbole ignoriert.
  • /ENTRY:krishtyMain; keine CRT-Funktionen überschrieben: CRT wird nicht mehr eingebunden. Alle CRT-Funktionen (_CxxThrowException() obwohl ich keine Ausnahmen benutze, _CrtDbgReport, __vcrt_uninitialize_critical, usw) sind undefiniert. Hat mit vorherigen Compiler-Versionen tadellos funktioniert.
  • /ENTRY:krishtyMain und CRT-Funktionen überschrieben: Selbes Verhalten, aber wahrscheinlich nur deshalb keine doppelten Symbole weil die CRT erst garnicht eingebunden wird. Hat mit vorherigen Compiler-Versionen tadellos funktioniert.
Okay. Kann da jemand Ordnung reinbringen und dieses Verhalten erklären?

Für mich klingt das, als ob sie sich gedacht haben: „Wenn jemand seinen eigenen Einsprungspunkt schreibt, können wir nicht garantieren dass die CRT initialisiert wird, und lassen sie direkt weg.“ (Das ist aber Quatsch, weil eine dynamisch eingebundene CRT durch DLL_PROCESS_ATTACH sehr wohl initialisiert wird.)

Kann ich ein Einbinden der CRT erzwingen? Ich habe versucht, MSVCRTD.lib explizit in die Linkerparameter zu schreiben, aber ohne Wirkung. (Spezialfall hard-coded?)

Bleibt mir sonst nur, entweder auf Einsprungspunkt oder auf die CRT zu verzichten?
Zuletzt geändert von Krishty am 01.08.2015, 10:38, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 364
Registriert: 03.10.2003, 12:47

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von NytroX »

Oha, was machste denn da für Krams? :-)
Welches Windows haste denn?
Weil die haben an der Runtime ja rumgemacht, biste jetz schon Win10 oder 7 oder 8 oder 8.1?
Benutzeravatar
Krishty
Establishment
Beiträge: 8239
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von Krishty »

7 noch. Ja, sie haben wirklich viel geändert. Uff. Wird ’n Kampf :(

Änderungen betreffend /ENTRY sind aber keine aufgelistet, zumindest habe ich keine gefunden.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 364
Registriert: 03.10.2003, 12:47

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von NytroX »

Ohmann, du hast recht.
Sobald man einen eigenen Entry setzt, macht der Linker Müll... Ich behaupte mal das hat nie einer getestet.
Der lässt sich auch nicht dazu überreden, die wieder reinzulinken, nicht mal unter nem anderen Namen.

Bisher hatte ich eigentlich nur das Problem, dass er aus unerfindlichen Gründen zur advapi32.lib linkt und dann dependencies zur entsprechenden DLL hat.
Und zwar wegen der Funktion "SystemFunction036" (=RtlGenRandom), die er aus meiner Sicht eigentlich nicht verwenden sollte weil sie nicht offizielle API ist (d.h. die exe läuft evtl. nach einem WinUpdate nicht mehr).
Warum braucht eine leere WinMain eine Random-Funktion ?!?
Die hab ich dann selbst implementiert, dann war die Dependency weg; das entspräche ungefähr deinem 2. Fall, ist aber halt keine CRT Funktion.

Weiß echt nicht wie man das hinbekommt, vielleicht hat ja noch jemand eine Idee?
NytroX
Establishment
Beiträge: 364
Registriert: 03.10.2003, 12:47

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von NytroX »

Habe gerade gesehen, dass ein

Code: Alles auswählen

#pragma comment(lib, "libvcruntime")
einige der Fehler behebt, also grundsätzlich scheint das Vorgehen zu funktionieren.
Die Frage ist halt in welchen libs das ganze Zeug drin ist, was ihm fehlt, linken zur msvcrt bringt jedenfalls nix.
Weiß der Teufel wie sie die runtime aufgeteilt haben; aber da machst du ja auch grad echt Plattform-spezifisches Zeugs...
Benutzeravatar
Krishty
Establishment
Beiträge: 8239
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von Krishty »

Tatsächlich, damit klappt’s!
http://blogs.msdn.com/b/vcblog/archive/2015/03/03/introducing-the-universal-crt.aspx hat geschrieben:If you link with the /nodefaultlib option, you will need to link several extra libraries when you link. For example, whereas you previously might have just linked msvcrt.lib in order to use the CRT DLL, you will now also need to link vcruntime.lib and ucrt.lib. Here is a table that shows which libraries you will need to link for each "flavor" of the libraries:

Release DLLs (/MD ): msvcrt.lib vcruntime.lib ucrt.lib
Debug DLLs (/MDd): msvcrtd.lib vcruntimed.lib ucrtd.lib
Release Static (/MT ): libcmt.lib libvcruntime.lib libucrt.lib
Debug Static (/MTd): libcmtd.lib libvcruntimed.lib libucrtd.lib
Die Allzweckwaffe:

Code: Alles auswählen

// Visual C++ 2015 by default does not link the CRT if the entry point is overriden. Force linking. Macros according to
//  "MSDN — Predefined Macros"; library names according to "Visual C++ Team Blog — Introducing the Universal CRT".
#if _MSC_VER >= 1900
#	if _DEBUG
#		if _DLL
#			pragma comment(lib, "vcruntimed")
#			pragma comment(lib, "ucrtd")
#		else
#			pragma comment(lib, "libvcruntimed")
#			pragma comment(lib, "libucrtd")
#		endif
#	else
#		if _DLL
#			pragma comment(lib, "vcruntime")
#			pragma comment(lib, "ucrt")
#		else
#			pragma comment(lib, "libvcruntime")
#			pragma comment(lib, "libucrt")
#		endif
#	endif
#endif
Danke NytroX, du hast mir wirklich meinen Hintern gerettet :)

Jammern:
Das hier geht natürlich NICHT:

Code: Alles auswählen

#	if _DEBUG
#		define VCRT_POSTFIX "d"
#	endif
#	if 0 == _DLL
#		define VCRT_PREFIX "lib"
#	endif
#	define VCRT_CONCAT(NAME) VCRT_PREFIX##NAME##VCRT_POSTFIX
#	pragma comment(lib, VCRT_CONCAT("vcruntime"))
#	pragma comment(lib, VCRT_CONCAT("ucrt"))
#endif
warning C4083: expected 'string'; found identifier 'VCRT_PREFIX'
Kann 2015 noch keine Makros in Pragmas. FUCK YOU, VC
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von Spiele Programmierer »

Ich glaube, dein Jammercode ist in normalen C++ 2015 auch nicht erlaubt.
Wenn man es wirklich verbinden würde, kämen ja doppelte Anführungszeichen raus.

Normalerweise fügt man Strings zusammen in dem man sie einfach hintereinander schreibt.
Hast du mal "#define VCRT_CONCAT(NAME) VCRT_PREFIX NAME VCRT_POSTFIX" probiert?
Außerdem solltest du "VCRT_POSTFIX" und "VCRT_PREFIX" in einem "#else"-Zweig definieren, auch wenn sie dann keinen Text enthalten und einfach leer sind.
Benutzeravatar
Krishty
Establishment
Beiträge: 8239
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von Krishty »

Spiele Programmierer hat geschrieben:Außerdem solltest du "VCRT_POSTFIX" und "VCRT_PREFIX" in einem "#else"-Zweig definieren, auch wenn sie dann keinen Text enthalten und einfach leer sind.
Ach verdammt, das war es! Undefiniert ist ja nicht "", sondern 0 … Danke; jetzt funktioniert es tatsächlich, mit 601 statt 665 Zeichen :)

Code: Alles auswählen

#if _MSC_VER >= 1900
	// Visual C++ 2015 by default does not link the CRT if the entry point is overriden. Force linking. Macros according to
	//  MSDN — "Predefined Macros"; library names according to Visual C++ Team Blog — "Introducing the Universal CRT".
#	if _DEBUG
#		define VCRT_POSTFIX "d"
#	else
#		define VCRT_POSTFIX ""
#	endif
#	if _DLL
#		define VCRT_PREFIX ""
#	else
#		define VCRT_PREFIX "lib"
#	endif
#	pragma comment(lib, VCRT_PREFIX "vcruntime" VCRT_POSTFIX)
#	pragma comment(lib, VCRT_PREFIX "ucrt" VCRT_POSTFIX)
#	undef VCRT_POSTFIX
#	undef VCRT_PREFIX
#endif
also FICK DICH FÜR ALLES ANDERE, VC
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8239
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Visual C++ 2015: /ENTRY und C Runtime

Beitrag von Krishty »

NytroX hat geschrieben:Bisher hatte ich eigentlich nur das Problem, dass er aus unerfindlichen Gründen zur advapi32.lib linkt und dann dependencies zur entsprechenden DLL hat.
Und zwar wegen der Funktion "SystemFunction036" (=RtlGenRandom), die er aus meiner Sicht eigentlich nicht verwenden sollte weil sie nicht offizielle API ist (d.h. die exe läuft evtl. nach einem WinUpdate nicht mehr).
Warum braucht eine leere WinMain eine Random-Funktion ?!?
Die hab ich dann selbst implementiert, dann war die Dependency weg; das entspräche ungefähr deinem 2. Fall, ist aber halt keine CRT Funktion.
Das hier landet unter x64 Release DLL in meiner EXE (Größe / Name / Quelle):

Code: Alles auswählen

  325: __scrt_fastfail                         utility_desktop.obj
  286: __scrt_initialize_thread_safe_statics   thread_safe_statics.obj
  151: _Init_thread_wait                       thread_safe_statics.obj
  101: _Init_thread_header                     thread_safe_statics.obj
   96: _Init_thread_footer                     thread_safe_statics.obj
   91: _Init_thread_notify                     thread_safe_statics.obj
   40: __scrt_uninitialize_thread_safe_statics thread_safe_statics.obj
	7: _guard_check_icall                      checkcfg.obj
	6: __vcrt_InitializeCriticalSectionEx      Import:VCRUNTIME140.dll
	3: _guard_check_icall_nop                  guard_support.obj
	1: _guard_dispatch_icall_nop               _guard_dispatch_.obj
Wird lustig, das zu ersetzen :roll:
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
NytroX
Establishment
Beiträge: 364
Registriert: 03.10.2003, 12:47

Re: [gelöst] Visual C++ 2015: /ENTRY und C Runtime

Beitrag von NytroX »

Oha, viel Spaß :mrgreen:

Achso, meine Implementierung sieht wie folgt aus, nur damit es komplett ist, falls jemand über den Thread stoplert und ähnliche Probleme hat.
Sollte man die RtlGenRandom dann doch tatsächlich benutzen und den Header "Ntsecapi.h" einlesen, dann verpufft die Definition/Implementierung einfach.
Den Quatsch habe ich einfach direkt unter meine WinMain gepackt.

Code: Alles auswählen

#if defined(WIN32) && defined(_MSC_VER) && !defined(RtlGenRandom)
extern "C" {
	unsigned char SystemFunction036(void* pBuffer, unsigned long bufferSize) {
		return 0;
	}
}
#endif
Antworten