Multithreaded-DLL



  • CodeFinder schrieb:

    Die sind eigenltich immmer dabei.

    Blödsinn! Bei VS2005 heissen die DLLs msvcr80.dll / msvcp80.dll / msvcm80.dll und sind bei (fast) keinem OS dabei!!! (möglicherweise bei Vista; aber sonst 100%ig bei keinem anderen).

    Wenn Du *ganz* kleine Programme erstellen willst, dann verzichte auf die CRT und stelle einen eigenen Entry-Point zur Verfügung!



  • Sry ich versteh nur Bahnhof 😃

    Also soll ich auf das Benutzen der C-Standardbibliothek verzichten. Heißt das ich darf eigentlich nur die windows.h benutzen?

    Und was du mit "eigenem Entry-Point" meinst weiß ich leider auch nicht.



  • Ok im Release-Mode wird die Datei mit DLL 7 kb groß ohne DLL 64 kb. Das ist noch annehmbar. Wenn ich damit auf der sicheren Seite bin werd ich mich wohl damit zufriedengeben müssen.



  • Spieler schrieb:

    Also soll ich auf das Benutzen der C-Standardbibliothek verzichten. Heißt das ich darf eigentlich nur die windows.h benutzen?

    Ja. Dann kannst Du Programme schreiben sie so klein wie möglich sind...

    Spieler schrieb:

    Und was du mit "eigenem Entry-Point" meinst weiß ich leider auch nicht.

    In den Projekteinstellungen unter "Linker|Advanced|Entry Point" oder "/ENTRY:"



  • Wenn Du *ganz* kleine Programme erstellen willst, dann verzichte auf die CRT und stelle einen eigenen Entry-Point zur Verfügung!

    Weisst du was dann alles nichtmehr geht, wenn man keine CRT linkt? Und was man für nen Tanz aufführen muss dass überhaupt noch *irgendwas* geht ohne CRT? Also zumindest mit dem VS ist das ein echter Krampf, ganz ganz grausam.
    Da würde ich mich eher nach einem anderen Compiler umsehen... vielleicht mal sehen was mit dem g++ oder Digital Mars so geht.

    Oder eben, sicherste Möglichkeit, nen guten optimierenden Macro Assembler nehmen :^)



  • hustbaer schrieb:

    Wenn Du *ganz* kleine Programme erstellen willst, dann verzichte auf die CRT und stelle einen eigenen Entry-Point zur Verfügung!

    Weisst du was dann alles nichtmehr geht, wenn man keine CRT linkt?

    Was meinst Du damit? Die CRT ist nur ein "Aufsatz" auf der WinAPI. Somit kannst Du auch ohne CRT alles machen, was man sonst auch machen kann 😉

    hustbaer schrieb:

    Und was man für nen Tanz aufführen muss dass überhaupt noch *irgendwas* geht ohne CRT? Also zumindest mit dem VS ist das ein echter Krampf, ganz ganz grausam.

    Was meinst Du damit?
    Die Release-Version von Folgendem Programm:

    #include <windows.h>
    #pragma comment(linker, "/ENTRY:myMain")
    
    extern "C" int __stdcall myMain()
    {
      ExitProcess(0);
    }
    

    hat keinerlei Abhängigkeiten zur CRT...
    Auch ist die Datei ganze 2,944 Bytes gross.
    Nach deaktivieren der Debug-Infos und abschalten des eingebetten Manifests ist es noch 2,048 Bytes gross.
    Und ein "dumpbin /ALL" erzeugt:

    Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
    Copyright (C) Microsoft Corporation. All rights reserved.

    Dump of file CPP_OhneCRT.exe

    PE signature found

    File Type: EXECUTABLE IMAGE

    FILE HEADER VALUES
    14C machine (x86)
    3 number of sections
    458B8284 time date stamp Fri Dec 22 08:00:20 2006
    0 file pointer to symbol table
    0 number of symbols
    E0 size of optional header
    103 characteristics
    Relocations stripped
    Executable
    32 bit word machine

    OPTIONAL HEADER VALUES
    10B magic # (PE32)
    8.00 linker version
    200 size of code
    600 size of initialized data
    0 size of uninitialized data
    1000 entry point (00401000)
    1000 base of code
    2000 base of data
    400000 image base (00400000 to 00403FFF)
    1000 section alignment
    200 file alignment
    4.00 operating system version
    0.00 image version
    4.00 subsystem version
    0 Win32 version
    4000 size of image
    400 size of headers
    0 checksum
    3 subsystem (Windows CUI)
    400 DLL characteristics
    No structured exception handler
    100000 size of stack reserve
    1000 size of stack commit
    100000 size of heap reserve
    1000 size of heap commit
    0 loader flags
    10 number of directories
    0 [ 0] RVA [size] of Export Directory
    2010 [ 28] RVA [size] of Import Directory
    0 [ 0] RVA [size] of Resource Directory
    0 [ 0] RVA [size] of Exception Directory
    0 [ 0] RVA [size] of Certificates Directory
    0 [ 0] RVA [size] of Base Relocation Directory
    0 [ 0] RVA [size] of Debug Directory
    0 [ 0] RVA [size] of Architecture Directory
    0 [ 0] RVA [size] of Global Pointer Directory
    0 [ 0] RVA [size] of Thread Storage Directory
    0 [ 0] RVA [size] of Load Configuration Directory
    0 [ 0] RVA [size] of Bound Import Directory
    2000 [ 8] RVA [size] of Import Address Table Directory
    0 [ 0] RVA [size] of Delay Import Directory
    0 [ 0] RVA [size] of COM Descriptor Directory
    0 [ 0] RVA [size] of Reserved Directory

    SECTION HEADER #1
    .text name
    9 virtual size
    1000 virtual address (00401000 to 00401008)
    200 size of raw data
    400 file pointer to raw data (00000400 to 000005FF)
    0 file pointer to relocation table
    0 file pointer to line numbers
    0 number of relocations
    0 number of line numbers
    60000020 flags
    Code
    Execute Read

    RAW DATA #1
    00401000: 6A 00 FF 15 00 20 40 00 CC j.ÿ.. @.Ì

    SECTION HEADER #2
    .rdata name
    5C virtual size
    2000 virtual address (00402000 to 0040205B)
    200 size of raw data
    600 file pointer to raw data (00000600 to 000007FF)
    0 file pointer to relocation table
    0 file pointer to line numbers
    0 number of relocations
    0 number of line numbers
    40000040 flags
    Initialized Data
    Read Only

    RAW DATA #2
    00402000: 40 20 00 00 00 00 00 00 00 30 40 00 58 30 40 00 @ .......0@.X0@.
    00402010: 38 20 00 00 00 00 00 00 00 00 00 00 4E 20 00 00 8 ..........N ..
    00402020: 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . ..............
    00402030: 00 00 00 00 00 00 00 00 40 20 00 00 00 00 00 00 ........@ ......
    00402040: 04 01 45 78 69 74 50 72 6F 63 65 73 73 00 4B 45 ..ExitProcess.KE
    00402050: 52 4E 45 4C 33 32 2E 64 6C 6C 00 00 RNEL32.dll..

    Section contains the following imports:

    KERNEL32.dll
    402000 Import Address Table
    402038 Import Name Table
    0 time date stamp
    0 Index of first forwarder reference

    104 ExitProcess

    SECTION HEADER #3
    .data name
    324 virtual size
    3000 virtual address (00403000 to 00403323)
    0 size of raw data
    0 file pointer to raw data
    0 file pointer to relocation table
    0 file pointer to line numbers
    0 number of relocations
    0 number of line numbers
    C0000040 flags
    Initialized Data
    Read Write

    Summary

    1000 .data
    1000 .rdata
    1000 .text

    Also ich finde es überhaupt nicht schwierig... oder was hast Du gemeint?



  • sehe ich das richtig das ein manifest nur dann benötigt wird wenn man die CRT 8 verwendet? ich versuche nämlich auch schon seit längerem meine appgröße im relase möglichst klein zu halten und bekam die CRT bisher einfach nicht raus. das hat teilweise auch schon dazu geführt das auf manchen systemen meine anwendung erst garnicht starten wollte. (FM: Fehler in Anwendungskonfiguration, installieren Sie die anwendung neu oder ähnlich) ich brauch die CRT nämlich auch nicht wirklich, das bissle strings hin und herkopieren kann man au selbst implementieren oder aus den win limps importiern (lstrcmp, lstrcpy, ...)
    meine app ist ein reiner server benötigt keine CRT, kein manifest und soll auf allen win systemen laufen ohne zusätzliche dll's.

    gibts vllt irgendwo tutorials zur größenoptimierung mit VS2005 wenn man REINE winapi apps machen möchte? bin in der richtung noch ned so fit.

    MfG
    RadiatioN


  • Mod

    @Jochen: Wenn wir bei C bleiben OK.
    Wie sieht das mit C++ aus, wenn dann statische/globale Objekte hinzukommen? new/delete sind IMHO komplett Abhängig von der CRT... oder irre ich mich da?



  • Martin Richter schrieb:

    @Jochen: Wenn wir bei C bleiben OK.
    Wie sieht das mit C++ aus, wenn dann statische/globale Objekte hinzukommen? new/delete sind IMHO komplett Abhängig von der CRT... oder irre ich mich da?

    Hmm... bei C++ wird es etwas komplexer, da hier noch vom Compiler spezielle Funktionen erwartet werden.
    Das Folgende Beispiel hat z.B: auch keinerlei Abhängigkeiten zur CRT:

    #include <windows.h>
    #pragma comment(linker, "/ENTRY:myMain")
    
    void* operator new(size_t size)
    {
      void *p = HeapAlloc(GetProcessHeap(), 0, size);
      //if (p == 0)
      //  throw 0;
      return (p);
    }
    void operator delete(void *pUserData)
    {
      if (pUserData != NULL)
        HeapFree(GetProcessHeap(), 0, pUserData);
    }
    
    class A
    {
    public:
      A()
      {
        a = 11;
        b = 2;
      }
      void Out()
      {
        DWORD dwWritten;
        WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), "Hello world", a, &dwWritten, NULL);
      }
      DWORD a;
      int b;
    };
    
    extern "C" int __stdcall myMain()
    {
      A a;
      A *pa = new A();
      pa->Out();
      delete pa;
      ExitProcess(0);
    }
    

    Wenn Du das "throw" wieder reinnimmst, dann wird es kompliziert... dieses hier ist jetzt vollkommen Compiler-Spezifisch... kann aber auch ersetzt werden, wenn Du weisst, was der Compiler genau erwartet.
    Das scheint mir auch der einzige Code-Teil der CRT zu sein, welcher nicht bei den Sourcen dabei ist!
    Hier findet sich z.B: mehr darüber:
    http://www.ddj.com/dept/windows/184416600

    Folgendes ist dann der (Test-)Code mit C++-Exceptions, welches auch keinerlei Abhängigkeiten zur CRT hat:

    #include <windows.h>
    #pragma comment(linker, "/ENTRY:myMain")
    // TODO: Linker-Options: /NODEFAULTLIB:msvcrt.lib"
    
    void* operator new(size_t size)
    {
      void *p = HeapAlloc(GetProcessHeap(), 0, size);
      if (p == 0)
        throw 0;
      return (p);
    }
    void operator delete(void *pUserData)
    {
      if (pUserData != NULL)
        HeapFree(GetProcessHeap(), 0, pUserData);
    }
    
    class type_info {
    public:
      virtual ~type_info() {}
        bool operator==(const type_info& rhs) const {return false;}
        bool operator!=(const type_info& rhs) const {return false;}
        int before(const type_info& rhs) const {return 0;}
        const char* name() const {return 0;}
        const char* raw_name() const {return 0;}
    };
    
    const DWORD CPP_EXCEPTION    = 0xE06D7363; 
    const DWORD MS_MAGIC         = 0x19930520;
    extern "C" void __stdcall _CxxThrowException(void * pObject, _s__ThrowInfo const * pObjectInfo)
    {
      const ULONG_PTR args[] ={ MS_MAGIC, (ULONG_PTR)pObject, (ULONG_PTR)pObjectInfo };
      RaiseException(CPP_EXCEPTION, EXCEPTION_NONCONTINUABLE, sizeof(args)/sizeof(args[0]), args);
    }
    
    class A
    {
    public:
      A()
      {
        a = 11;
        b = 2;
      }
      void Out()
      {
        DWORD dwWritten;
        WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), "Hello world", a, &dwWritten, NULL);
      }
      DWORD a;
      int b;
    };
    
    extern "C" int __stdcall myMain()
    {
      A a;
      A *pa = new A();
      pa->Out();
      delete pa;
      ExitProcess(0);
    }
    

    Und das mit den globalen Objekten wird man auch in der Griff bekommen, da ja hier die Sourcen vorliegen 😉



  • @Jochen Kalmbach:
    Genau solche Sachen meinte ich mit "fürchterlich kompliziert" 🙂
    Sobald du Exceptions verwenden willst heisst es basteln. Sobald du dynamic_cast verwenden willst heisst es noch mehr basteln. RTTI im Allgemeinen -> basteln.
    Weiters kannst du in deinem Programm zwar Exceptions werfen, aber nicht fangen. Stack Unwinding -> wieder in der CRT implementiert.

    Wenn man also reinen C-Code schreiben will, bzw. bloss "etwas schöneren C-Code" mit C++, dann geht es vielleicht. Trotzdem würde ich mich da eher nach einem Compiler umsehen wo man das etwas einfacher hinbekommt als mit dem MSVC 🙂


Anmelden zum Antworten