Announcement

Collapse
No announcement yet.

Fedora 29 Might Make Change To Eliminate Unnecessary Linking

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #31
    Originally posted by Weasel View Post
    Given the nonsense I had to share, I think it's safe to say I'm the biggest troll in this discussion
    Fixed.

    Comment


    • #32
      Originally posted by F.Ultra View Post
      Sorry to burst that bubble dude but this is really happening, I've programmed Windows applications for decades and have seen many young devs fall for this.

      If your application is linked with runtime A and you then use a DLL that is linked with runtime B and your process calls a function in that DLL then Windows will switch the current runtime context for your thread to B and when the function returns it will switch back to A again. However the major bug here is that if code in the DLL calls back to your application then the runtime context is still B and not A.

      You can test this extremely easy yourself with libraries such as cURL or Expat. E.g with Expat you define callbacks to handle when an XML-tag starts and ends:
      Code:
      struct XMLUSERDATA {
      char *test;
      };
      
      static void xml_end (void *udata, const XML_Char *name)
      {
      }
      
      static void xml_start (void *udata, const XML_Char *name, const XML_Char **atts)
      {
      struct XMLUSERDATA *userdata = udata;
      
      userdata->test = strdup (name); /* we allocate a string in our own code here */
      }
      
      int main (int argc, char **argv)
      {
      struct XMLUSERDATA userdata;
      memset (&userdata, 0, sizeof userdata);
      
      XML_Parser xml = XML_ParserCreate (NULL);
      
      XML_SetUserData (xml, &userdata);
      XML_SetElementHandler (xml, xml_start, xml_end);
      
      XML_Parse (xml, argv[1], strlen (argv[1]), 1);
      XML_ParserFree (xml);
      
      free (userdata.test); /* this will crash because the previous strdup() was done with the C runtime context of libexpat and not our application */
      }
      If this application is linked with a different C runtime than libexpat is (which e.g can happen if one of them is debug-compiled) then this code crashes hard even though both the call to strdup() and free() is done only in our own code (all form of error checking have been ignored due to visibility).
      strdup doesn't seem to be a Windows runtime function, or what header should I include, are you sure this is Windows code and not Linux?

      This runtime context thing stinks of bullshit to me, and not because you're wrong, but it is impossible: two different libraries have two separate global spaces and everything, so even if they did use a global variable for it, there would be no clash. If you have any links for windows about this (since that was the context) then I'd like to read it.

      Originally posted by F.Ultra View Post
      Yes libraries that originate on Windows or have a large usebase on Windows have their own free() functions, not because such a function make a library better but because they are necessary on Windows while they are completely useless on every other system (unless of course if we talk about objects and opaque handlers since their destruction can be more complex than a simple call to free()).
      This is why I can't take you seriously, and this has nothing to do with Windows.

      No library worth its salt will ever let the destruction process up to the caller, unless the caller is responsible for creating and allocating the object. It's just insane design and spagetti. How about you name some such libraries (and the respective APIs) then so I can laugh at the guys who designed them?

      Comment


      • #33
        Originally posted by coder View Post
        That's just a trick used for testing, tracing, etc. It's not standard practice. Effectively, the symbols are bound to the libraries in which they were found at link time.
        A trick that results in a shit design? Yeah, like I said, never ceases to amaze me.

        Here's a hint: if something is not standard practice, it should have its own specialized tool, and design not catered to it. Like, for example, DLL injection in Windows.

        Originally posted by coder View Post
        We're not. It was your example that you were holding up as some sort of desirable trait. PAL and I were pointing out that it's quite hazardous, in practice.
        Nope. The argument was about multiple libraries existing in the same address space. For example:

        Your process -> libA.1 -> libB
        Your process -> libC -> libA.2

        So your process depends on both libA.1 and libC, that's it. libC, being totally separate from your process, depends on libA.2, and yet there's no conflict on Windows. Imagine how pathetic ELF's design is when updating libC can break your process simply due to a retarded conflict because there's no separation.

        Originally posted by coder View Post
        We know this. We're saying that when libraries at multiple levels of a software stack share a common dependency, it's likely they're passing objects from this 3rd library between them. That will usually fail pretty hard.
        No, see above, and this scenario is VERY common. Your process does not care about libA.2 and all it knows is that it links to libA.1 and libC. If any conflicts arise from another library loading something, then the design is pure garbage.

        This is the complete anti-thesis to modularity and encapsulation.

        Originally posted by coder View Post
        They incremented the major version of libstdc++, for this. Again, see point about why linking different versions of the same library isn't a good idea.
        wtf are you talking about? You don't control what another shared object depends on, and neither should you care in a proper environment. The whole point of libraries is that they are modules and able to be replaced/updated separately.

        I already linked it and it was clear as day: just because YOU use version ABC of libstdc++ does not mean that your caller does, and neither should you CARE what libstdc it uses. If you do care and hardcode this assumption, your library stinks of crap design, sorry.

        Originally posted by coder View Post
        This makes it pretty clear what the problem is. You're just a sad little Windows programmer pissed at the ascendancy of Linux and how it's not broken and encumbered like Windows userland.
        As if claims made my clowns have any merit. All you've provided are claims, because I know you won't find links of anyone sane defending the kind of bullshit that's here. In fact, this thread is perfect proof: Fedora needs to do something that simply is not a problem and has never been on Windows.

        Originally posted by coder View Post
        If you think ELF and Linux shared libraries are so broken, maybe don't use them. No need to cry about it and insult people on here like a small child who hasn't had his nap.
        And who said I use them? Not to mention your argument is just that of a child who cannot accept criticism for his favorite, even when it's backed by facts.

        Good thing that there's this thing called Wine which implements a superior loader than native for libraries: it can actually use DLLs. And no, you don't tell me what to use or what to contribute code to. I absolutely despise Windows as the operating system itself, but it does have many technical merits over Linux way of doing things, and this is one of them.

        And I only insulted him back, just saying.

        Comment


        • #34
          Originally posted by coder View Post
          Dude, this is a Linux forum. I don't know any Windows-exclusive libraries, having spent the last couple decades on Linux.
          So why did you even argue about Windows' superior library design if you don't know? WTF.

          I get it, you hate Windows, and thus it must mean that *everything* about it is worse than Linux -- that's the clown way of thinking, instead of separating each technical merit into its own context.

          Originally posted by coder View Post
          Since C doesn't have destructors, it's natural to have some sort of "destroy" function. In that sense, it's common practice for C libraries.
          Destructors are functions too, just because you're not aware of them doesn't mean they aren't implemented by the compiler under the hood (they even have a mangled name). There's literally no difference, at the binary level, which is what matters.

          Originally posted by coder View Post
          No, but I'm saying that wrapping up all of your data types in hermetically-sealed boxes, and restricting your APIs to use only POD types does. And copying data or wrapping and unwrapping as it moves up and down your software stack can quickly burn performance.
          Everything is a POD type at the binary level. Functions are not part of the objects at the storage level, they're normal functions. While virtual functions are stored in a vtable (function pointer array), that's absolutely no different than doing it yourself in a "POD type" if that's your thing.

          You can provide a pointer to your type to your caller as long as the caller knows about it, i.e. it directly links to your library. It doesn't have to be POD.

          But the standard library that your library uses is NOT imported by the caller, so it is NOT AWARE of the type you return. It can import its own standard library for it, but that violates the one definition rule of C++ because it's not the same library. Yes this is a violation of the LANGUAGE.

          I already linked this. No need to repeat myself.

          Imagine if your library returns a type of libfoobar that it depends on. But the caller doesn't import libfoobar and doesn't have libfoobar's headers. How the fuck can the caller even compile the function then? (without importing libfoobar, which is just retarded) The standard library is not different. Only types defined in your library are allowed to be exported, because it's only those types you define in the library's headers that exports its APIs.

          And std types are no such thing!

          Stop this idiotic idea that "there's only one standard library". No there's not. Linux has made this fatal mistake in the past because there was only GCC, now you even have two of them (Clang) not to mention ABI breakage from GCC's. Each import of it is DIFFERENT in each library.
          Last edited by Weasel; 04 July 2018, 05:17 PM.

          Comment


          • #35
            Originally posted by Weasel View Post
            So your process depends on both libA.1 and libC, that's it. libC, being totally separate from your process, depends on libA.2, and yet there's no conflict on Windows. Imagine how pathetic ELF's design is when updating libC can break your process simply due to a retarded conflict because there's no separation.
            I don't know why you're trying to have it both ways. Either libC should not expose any datatypes from libA and then it doesn't matter which version of libA it's using, or else libA is a public dependency and its version must match other libA's visible in that scope.

            Originally posted by Weasel View Post
            wtf are you talking about? You don't control what another shared object depends on, and neither should you care in a proper environment. The whole point of libraries is that they are modules and able to be replaced/updated separately.
            No. In Windows, everybody ships around separate copies of their requisite DLLs to keep out of DLL Hell. So, you think this is natural.

            In Linux, RPM and Debian have robust version management, making it possible to have a single repository of userspace libraries that are shared system-wide. This benefits security, since you can update these libraries with security fixes (and other enhancements) and all apps using them will automatically benefit.

            Originally posted by Weasel View Post
            I already linked it and it was clear as day: just because YOU use version ABC of libstdc++ does not mean that your caller does, and neither should you CARE what libstdc it uses. If you do care and hardcode this assumption, your library stinks of crap design, sorry.
            I think you're just bitter that you can't use C++ datatypes in your APIs as freely and easily as Linux.

            Originally posted by Weasel View Post
            And who said I use them? Not to mention your argument is just that of a child who cannot accept criticism for his favorite, even when it's backed by facts.
            All you've shown is you have more free time, a lack of decorum, and a bigger chip on your shoulder. All you've done is tried to spin Windows DLLs' deficiencies and limitations as assets and virtues. Since we're not buying it, I think you're just wasting your time and making yourself unwelcome.

            I see this as a pointless argument from the outset. I have nothing to prove. Again, if you don't like it, leave.

            Comment


            • #36
              Originally posted by Weasel View Post
              So why did you even argue about Windows' superior library design if you don't know? WTF.
              I was arguing against your assertions about what constitutes best practices. Maybe best for Windows, but Linux userspace has different strengths & weaknesses and has adopted different practices.

              Originally posted by Weasel View Post
              I get it, you hate Windows, and thus it must mean that *everything* about it is worse than Linux -- that's the clown way of thinking, instead of separating each technical merit into its own context.
              I didn't say that. After a few years developing on Windows, I went over to Linux. Then, briefly back to Windows (by circumstances, not choice). I just found I preferred liked developing on Linux better. I would never say *everything* is better or worse about either camp, and there are things I imagine about an ideal userspace which I have never seen in the wild.

              Originally posted by Weasel View Post
              Destructors are functions too, just because you're not aware of them doesn't mean they aren't implemented by the compiler under the hood (they even have a mangled name). There's literally no difference, at the binary level, which is what matters.
              You missed my point. I was saying C libraries need to expose functions for cleaning up their objects, so it's natural for those functions also to deallocate them, in cases where the objects were allocated by a corresponding library function. This maps to the destructor and delete operator of C++, combined.

              However, because C++ has destructors, you don't find that same need to expose cleanup functions and people generally fall back on the default delete operator. So, your point about library design and cleanup functions naturally applies to C libraries (such as those you cited), but not because they're necessarily trying to abstract the allocator.


              Originally posted by Weasel View Post
              Only types defined in your library are allowed to be exported, because it's only those types you define in the library's headers that exports its APIs.
              Again, trying to spin a Windows limitation as a virtue.

              Linux is rife with public library dependencies. Heck, the entire Gnome and KDE ecosystems are built on this model. Yes, it has pitfalls. That's why version management is so important, on Linux. But, given that foundation, this is a net-strength, not the grievous deficiency as which you paint it, with all your hyperbolic and apocalyptic rhetoric.

              Comment


              • #37
                Originally posted by coder View Post
                I don't know why you're trying to have it both ways. Either libC should not expose any datatypes from libA and then it doesn't matter which version of libA it's using, or else libA is a public dependency and its version must match other libA's visible in that scope.
                OMG dude, wtf? When did I say it exposes any data types? In fact, that's beyond retarded design, like I said the only exports that a library can expose within its interface (headers) must be either its own types, or basic types. No standard library types, nothing else. The interface header must not #include anything except other headers part of the same library (if any, usually not). This means no standard library and NO OTHER DEPENDENCIES.

                With that said, this has nothing to do with exposing it. In my example, your process depends on libA.1 and libC. That's it. As long as these two dependencies are satisfied and they're binary compatible (which they should), and respect the behavior contract, the process must run, period. Nothing from libA.2 is exposed. NOTHING.

                With ELF, this is NOT THE CASE because you have to care about the dependencies of THOSE libraries too, if they conflict with your app or not. This is pure dependency hell. Let's say your process uses "SomeFunction" symbol from libA.1 -- which works perfectly fine. One day, libC gets updated to use libA.2 internally, but it's completely ABI compatible to before, it exposes the same interface etc... this is just an internal implementation detail that your process should not give a shit about.

                Unfortunately, libC also uses a symbol called "SomeFunction" from libA.2 because the dev was retarded and kept the function names when updating the library with an ABI-incompatible version. What might happen is that libC will now link against the libA.1 SomeFunction (because it was loaded first by your process, same shit as LD_PRELOAD) which is binary incompatible and will cause a stack corruption or a crash.

                Why the fuck should your process, which only uses libA.1 and libC, care about the internal implementation or dependencies of either of those libraries? This breaks every encapsulation and modularity design in existence.

                ELF is just garbage.

                But you see, they actually found this as a problem that's why they added versioned symbols (yes fanboys, they actually added a "capability" similar to DLLs, so much for your arguments) -- which nobody uses because they weren't there from the beginning.

                If libC statically linked libA.2, things would work, but with dynamic linking they don't -- this PROVES how putrid the ELF design is compared to DLL. (for DLL it doesn't matter if it's static or dynamically linked, behavior is the same)

                Originally posted by coder View Post
                No. In Windows, everybody ships around separate copies of their requisite DLLs to keep out of DLL Hell. So, you think this is natural.

                In Linux, RPM and Debian have robust version management, making it possible to have a single repository of userspace libraries that are shared system-wide. This benefits security, since you can update these libraries with security fixes (and other enhancements) and all apps using them will automatically benefit.
                This has nothing to do with what we're discussing.

                Originally posted by coder View Post
                I think you're just bitter that you can't use C++ datatypes in your APIs as freely and easily as Linux.
                You're violating the language ODR and call me bitter? Go post your answer on stackoverflow and watch it down votted to the abyss. What a clown argument.

                Off topic, but, I hate the standard library. I personally rarely use it, because it makes you dumber and bloated code. So you got it completely wrong there anyway. It wasn't me who used it in examples anyway.

                The standard library is not different than any other library, and must not be treated any differently, and this is a fact mind you. Imagine if in your header, your libC uses data types from libfoo, how can someone using the interface (your header) have those types without also #including libfoo? An interface header should NEVER #include any file that's not part of the interface. That means no #include <stdcrap> either.

                Want proof? Go compile with -nostdinc++ which is your right to do (in your app) and try to use a header of one of your bullshit library interfaces that use the standard library. If it fails to compile, your library is garbage. Period.

                Originally posted by coder View Post
                All you've shown is you have more free time, a lack of decorum, and a bigger chip on your shoulder. All you've done is tried to spin Windows DLLs' deficiencies and limitations as assets and virtues. Since we're not buying it, I think you're just wasting your time and making yourself unwelcome.
                Who the fuck do you think you are? Is this your site or something? Bullshit is not welcome so why are you here?

                You haven't named a single deficiency in DLL (compared to ELF) that I haven't debunked -- with facts (and links). Get over it and provide links for your absolute bullshit, because your fanboy claims have zero value.
                Last edited by Weasel; 05 July 2018, 07:49 AM.

                Comment


                • #38
                  Originally posted by coder View Post
                  I was arguing against your assertions about what constitutes best practices. Maybe best for Windows, but Linux userspace has different strengths & weaknesses and has adopted different practices.
                  Are you intentionally acting stupid or did you not click on a single link I provided? Your "different strengths" VIOLATE THE C++ LANGUAGE RULES (also C).

                  It is a WRONG WAY TO CODE, period (and if you don't like it, DON'T USE C/C++, it's that easy). Same as relying on type-aliasing not existing and then wondering why "it broke my code" with new or different compiler. Christ.

                  Reminds me of people who used that and they whined GCC broke their code when they turned on -fstrict-aliasing when they were violating the language before that so it wasn't GCC's fault at all.

                  Originally posted by coder View Post
                  You missed my point. I was saying C libraries need to expose functions for cleaning up their objects, so it's natural for those functions also to deallocate them, in cases where the objects were allocated by a corresponding library function. This maps to the destructor and delete operator of C++, combined.

                  However, because C++ has destructors, you don't find that same need to expose cleanup functions and people generally fall back on the default delete operator. So, your point about library design and cleanup functions naturally applies to C libraries (such as those you cited), but not because they're necessarily trying to abstract the allocator.
                  Destructors are just normal functions, and if you expose them (via header) then they are automatically exposes just like a C function. Why does it matter if it's implicit or explicit? The binary is the same.

                  You are completely wrong and I will link again another piece (this time it's what is on top at Google search):

                  I know that, in Windows, memory must be deallocated in the same module that allocated it. I have 2 DLLs built with different C++ compilers (VS 6 and VS 2015). In the VS 2015 module, I have an expo...


                  Excerpt:
                  Originally posted by Cody Gray
                  The standard (and recommended) way to solve this is for each module to provide its own exported AllocMem and FreeMem functions (or whatever you want to call them—the names are not important).
                  Seriously just stop with this bullshit misinformation of "not needed on Linux". It may have not been needed when GCC was the only compiler (but now there's also Clang), but it was violating the language, just as when GCC was not implementing strict aliasing long ago.

                  There's no excuse for that. None. If you violate the language and refuse to accept you're wrong, you're the trashiest tier of C/C++ programmer in existence.

                  Originally posted by coder View Post
                  Again, trying to spin a Windows limitation as a virtue.

                  Linux is rife with public library dependencies. Heck, the entire Gnome and KDE ecosystems are built on this model. Yes, it has pitfalls. That's why version management is so important, on Linux. But, given that foundation, this is a net-strength, not the grievous deficiency as which you paint it, with all your hyperbolic and apocalyptic rhetoric.
                  This is not a Windows limitation this is a C/C++ language thing.

                  For all those people who find it more convenient to bother you with their question rather than to Google it for themselves.


                  Your use of a data type external to your header, such as the standard library, that may not be identical, is a direct violation of ODR.

                  If you DO use a data type in a header interface you must provide the exact header that defines that data type for the app that wants to use your library.

                  And the standard library is far from "exact" considering how much it can change even amongst the same compiler, nevermind different compilers (GCC vs Clang vs VC++, and so on). Which violates ODR.
                  Last edited by Weasel; 05 July 2018, 08:02 AM.

                  Comment


                  • #39
                    One last thing: typedefs are aliases not new data types. Struct define new data type (even in C), not typedef.

                    So it's perfectly OK to use size_t and such as long as they are always the same typedef (which they should, since they're standardized, at least on a given architecture). It is also perfectly ok to use uint32_t and so on in a library interface.

                    This is the exact reason that typedefs were made to be aliases instead of "creating new types". The distinction is crucial. (in fact, in C++ it matters a whole lot more than in C, because template instantiations are done based on the underlying type, so if "uint32_t" is same as "unsigned int", then you can't provide two overloads or instantiations for both of them since they're the SAME).

                    Lastly, see the first bullet point, which is about ODR and interfaces: https://stackoverflow.com/a/43970681


                    I think it's funny you think that DLL is not useable on Linux though, which kind of, you know, shows its direct superiority to ELF on the same OS. In case you need some help: https://www.winehq.org/ (yes, it loads DLLs and avoids pitfalls of ELF, shocking)
                    Last edited by Weasel; 05 July 2018, 08:37 AM.

                    Comment


                    • #40
                      Originally posted by Weasel View Post
                      strdup doesn't seem to be a Windows runtime function, or what header should I include, are you sure this is Windows code and not Linux?
                      Now this was just a quick example that I created just for this moment. strdup() is part of the C runtime library even though Microsoft in their infinite wisdom have decided to make it "deprecated" in newer versions of VS where they have renamed it as _strdup()... https://docs.microsoft.com/en-gb/cpp...-wcsdup-mbsdup

                      Originally posted by Weasel View Post
                      This runtime context thing stinks of bullshit to me, and not because you're wrong, but it is impossible: two different libraries have two separate global spaces and everything, so even if they did use a global variable for it, there would be no clash. If you have any links for windows about this (since that was the context) then I'd like to read it.
                      Global variable? I don't know where you get any reference to global variables from. When I first found out about this problem in Windows some 15 years ago (when debug compiling a program and suddenly got a crash in something like the free() from my example above) there where MSDN articles about this, for some reason I cannot find them anymore (it's been quite a while) but atleast they still have this one: https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/ms235460(v=vs.110) :
                      If you design your DLL so that it passes CRT objects across the boundary or allocates memory and expects it to be freed outside the DLL, you restrict the DLL users to use the same copy of the CRT library as the DLL. The DLL and its users use the same copy of the CRT library only if both are linked with the same version of the CRT DLL.
                      Which neatly describes the very thing that I see even though there once (or still do, just that I cannot currently find it) where an article on how the process thead changed runtime context. However the main problem here is that what is described in the quoted text above also can happen inside 100% your own code as in my small example.

                      Originally posted by Weasel View Post
                      This is why I can't take you seriously, and this has nothing to do with Windows.

                      No library worth its salt will ever let the destruction process up to the caller, unless the caller is responsible for creating and allocating the object. It's just insane design and spagetti. How about you name some such libraries (and the respective APIs) then so I can laugh at the guys who designed them?
                      Yes this have exactly yo do with Windows unless we talk about objects (which I escpecially mentioned in the post you quoted so why you now try to bring up allocated objects is insidious).

                      Not every library creates objets, some of them manipulate i.e strings or return created void * arrays. Having a library-specific free() function for such standard C data types are beyond stupid unless you use the library on Windows where it's required for their problem of libc-version mixing.

                      But you wanted examples.

                      Here is a perfectly fine hash-library: https://launchpad.net/hashit where you can get the complete list of keys or values as a NULL terminated array. Since the library is created on Unix and are only used on Unix it has not idiotic x_free() function which of course means that you cannot use these two functions in Windows without a potential crash.

                      Another example is libneon which was the reference implementation for a WebDAV client: https://web.archive.org/web/20070925040920/http://www.webdav.org/neon/ , it originally didn't have the ne_free() function until people ported it to Windows and looking at the include file it's also clearly demonstrates that this was added just to make it work on Windows:
                      Code:
                      #ifdef WIN32
                      void ne_free(void *ptr);
                      #else
                      #define ne_free free
                      #endif
                      Yet another example is libcurl: https://curl.haxx.se/libcurl/ , it also didn't have any curl_free() until v7.10 where it was added yet again due to Windows.

                      Comment

                      Working...
                      X