Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Mooey Cow
Jan 27, 2018

by Jeffrey of YOSPOS
Pillbug
I like C++ and think RAII and templates are beautiful animals and creatures of God. I mostly use C# for work and I'm often annoyed that what could be like 5 lines of clear C++ either has to be 100 copy-pasted lines, or something that will generate loads of garbage. And all this "syntactic sugar" that expands to a multi-kb class that'll be instantiated every time a function is called. Ugh. There's a complex language.

I wouldn't call the project my horror is from C++ though. It's basically made out of macros and WTFs. It has a scripting engine where the script data is just a big pile of bytes that gets cast to function pointers and whatnot. There's a bunch of ifdefs and macros to fix up some stuff in case a platform doesn't support unaligned access because lol that obviously bit them in the rear end when they tried to run it on something that wasn't x86 :downs:

Xerophyte posted:

This probably compounds the horror, but that particular Terrible No Good Very Bad Idea seems to have come from Bjarne himself.

That said, I'm fairly sure it's not actually valid C++ to replace placement new nowadays.


E: Apparently classes are still allowed to provide their own specialized placement new members, just that unlike the regular new and delete operators the placement can't have global replacements. Oh, C++.

Anyhow, the constructor for the class should still get called after placement new adds the item to the array, same as a regular operator new. The canonical standard library placement new is void* operator new(size_t s, void* p) { return p; }, they're not expected to do things. Overriding placement new just to provide a more exciting syntax for emplace_back is still a horror.

At least Bjarne's thing seems to be some sort of allocator. Placement new on an allocator looks weird but might be possible to figure out, but on a list it just looked like an obvious bug. Also yes, the constructor would be called in this case... Just remember that Add() does not actually add anything, it just moves the end pointer or whatever one step, and you'll have to construct your thing yourself. They've cut a vector in half to expose its gross guts :gonk:

I can think of like 50 ways to do this in a better way, even before C++11. We worked on a 3DS project many years ago, and the compiler (which always stopped working because its license ran out every week) did not support that, but I managed to add rudimentary move semantics anyway (basically a member function called "move" that'd be called instead of the copy constructor when possible. Groundbreaking stuff really). My lovely custom vector even had a proper emplace function :smug:

Adbot
ADBOT LOVES YOU

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man
Need to get the rest of the Knights of C++ in here, like slurps mad rips and rjmccall and hackbunny. C++ is a great language though I will admit the ratio of doing something useful : doing something masturbatory can be... off.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

Linear Zoetrope posted:

No, you mathematically can't fully specify any turing-complete language in BNF because BNF is context free which is a strict subset of Turing Completeness (since BNF has a bijection with pushdown automata).

What? Just because a language is turning complete doesn't mean it's syntax is, or would need to be.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
The past year, for the first time in my life, I could finally use C++ to its fullest extent for real software (vs personal experimentation) and I have to say I greatly enjoyed it and have had remarkably few issues. Biggest issues were:
  • lack of a standardized event loop/thread pool library
  • std::function not supporting movable but non-copyable functors
  • we really need a syntax for monadic expressions, because navigating chains of nullable pointers, std::weak_ptrs, std::optionals etc. is hell
  • too easy to use a moved-from object and e.g. accidentally dereference a null smart pointer
but I'm not complaining much. The first two only mean hand-rolling code that should be in a standard library (or using third party libraries, that for the time being I've opted not to), the third is just a nice-to-have, and the fourth is an issue that would probably be caught by code analysis (haven't had time to run one yet because we're disrupting here, but soon). I really enjoyed some of the "controversial" additions to the standard library, like the std::chrono stuff, that spared me a ton of headaches (I really wish there was a better way to format a date-time than strftime, though) and seemed tailor made for my scenario, where I juggle up to four different timestamp types at the same time

Best part overall was I got to pick my favorite degree of compromise between generic and polymorphic on a case-by-case basis, which no other language that I know of allows. Worst part? The different degrees of support and/or quirks between the various compilers, that you can often not be sure whether they're bugs or not

I also can't imagine any other language that could form the core of a multi-platform (iOS, Android, Windows) application and interoperate with languages as diverse as Swift, Java and C# and not be a hell of manual resource management like C

C++ is good and I like it

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

It seems like the people who really like C++ are the ones who are real experts at C++. That's not the case with proponents of every language.

I'm not sure if that means its good or bad.

Absurd Alhazred
Mar 27, 2010

by Athanatos

hackbunny posted:

I really enjoyed some of the "controversial" additions to the standard library, like the std::chrono stuff, that spared me a ton of headaches (I really wish there was a better way to format a date-time than strftime, though) and seemed tailor made for my scenario, where I juggle up to four different timestamp types at the same time

Have you taken a look at date.h? We've used it at work to great effect.

Thermopyle posted:

It seems like the people who really like C++ are the ones who are real experts at C++. That's not the case with proponents of every language.

I'm not sure if that means its good or bad.

I like C++ and I am by absolutely no means an expert.

fritz
Jul 26, 2003

QuarkJets posted:

You could describe pretty much every popular programming language in that way

Not at all, some of them have decent build systems.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Absurd Alhazred posted:

I like C++ and I am by absolutely no means an expert.

Well my hypothesis has been utterly destroyed.

Absurd Alhazred
Mar 27, 2010

by Athanatos

Thermopyle posted:

Well my hypothesis has been utterly destroyed.

:twisted:

To be fair, I have also been repeatedly told that I am a glutton for punishment.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

ratbert90 posted:

Lol c++ isn’t complicated. What in the gently caress are you talking about?

one of my first hurdles with commercial c++ came when I realized that microsoft alone used over sixteen different string types in the windows api ( char*, wchar_t*, LPSTR, LPTSTR, LPWSTR, LPCSTR, LPCTSTR, LPCWSTR, BSTR, OLESTR, UNICODE_STRING, String, string, wstring, _bstr_t, CString)

SardonicTyrant
Feb 26, 2016

BTICH IM A NEWT
熱くなれ夢みた明日を
必ずいつかつかまえる
走り出せ振り向くことなく
&



There are no bad programming languages, there are only bad programmers.

VikingofRock
Aug 24, 2008




Bruegels Fuckbooks posted:

one of my first hurdles with commercial c++ came when I realized that microsoft alone used over sixteen different string types in the windows api ( char*, wchar_t*, LPSTR, LPTSTR, LPWSTR, LPCSTR, LPCTSTR, LPCWSTR, BSTR, OLESTR, UNICODE_STRING, String, string, wstring, _bstr_t, CString)

TBH this doesn't really sound like a problem with C++

Absurd Alhazred
Mar 27, 2010

by Athanatos
https://twitter.com/johnregehr/status/1005877520208498688

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Bruegels Fuckbooks posted:

one of my first hurdles with commercial c++ came when I realized that microsoft alone used over sixteen different string types in the windows api ( char*, wchar_t*, LPSTR, LPTSTR, LPWSTR, LPCSTR, LPCTSTR, LPCWSTR, BSTR, OLESTR, UNICODE_STRING, String, string, wstring, _bstr_t, CString)

You're forgetting _TCHAR * :eng101: There are reasons for each of them, though. Good reasons? I don't know

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

VikingofRock posted:

TBH this doesn't really sound like a problem with C++

im pretty sure everyone wouldn't make their own string type if strings in C++ didn't suck nuts.

Captain Cappy
Aug 7, 2008


It's cool.

Athas
Aug 6, 2007

fuck that joker

hackbunny posted:

You're forgetting _TCHAR * :eng101: There are reasons for each of them, though. Good reasons? I don't know

Unix is even older than Windows, so how come the POSIX API is (relatively speaking) so much simpler? It's at least not nearly as typedef-polluted. Also the type names are not in SCREAMING CAPS, but that's probably a pretty subjective preference.

QuarkJets
Sep 8, 2008

Bruegels Fuckbooks posted:

im pretty sure everyone wouldn't make their own string type if strings in C++ didn't suck nuts.

strings in C++ aren't great but they aren't terrible either

the problem here is really 1 org creating a new string type over and over and over

DaTroof
Nov 16, 2000

CC LIMERICK CONTEST GRAND CHAMPION
There once was a poster named Troof
Who was getting quite long in the toof

Bruegels Fuckbooks posted:

im pretty sure everyone wouldn't make their own string type if strings in C++ didn't suck nuts.

maybe i don't have enough experience, but i never had many complaints about std::string. especially compared to the special snowflakes involved every time you needed to manipulate strings in c

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Formally, every programming language has a hierarchy of well-formedness conditions, and you can imagine each of these as inducing its own language, with each step creating a subset-language of the previous. The lexical language is usually regular, although languages with nestable multi-line comments are a notable exception. The grammatical language is usually context-free, and in some sense this is true even for languages with lookup-sensitive parsers like C++, where there might just be more than one valid parse of a given input if you ignore contextual information. As for the actual language, well, it’s common for languages to have at least some well-formedness conditions that aren’t context-free, e.g. lexical lookup of unqualified names so that obvious typos in variable references can be reported immediately. That alone is well beyond the capabilities of a PDA, much less any sort of type system, even if deciding it isn’t actually Turing-complete.

SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

Athas posted:

Unix is even older than Windows, so how come the POSIX API is (relatively speaking) so much simpler? It's at least not nearly as typedef-polluted. Also the type names are not in SCREAMING CAPS, but that's probably a pretty subjective preference.
Backwards compatibility.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Athas posted:

Unix is even older than Windows, so how come the POSIX API is (relatively speaking) so much simpler? It's at least not nearly as typedef-polluted. Also the type names are not in SCREAMING CAPS, but that's probably a pretty subjective preference.

Oh it's easy, they just ignored Unicode for a long time. They never upgraded the API to wchar_t and just toughed it out, requiring conversion of all strings to/from the current encoding until someone came up with a magic universal encoding (UTF-8), and even then it took a long time before it was adoped

Then you have to consider that Windows had to run on 16 bit machines with more than 64 KB of RAM, requiring segmentation: so you not only had char * and wchar_t *, but also char __near *, char __far *, wchar_t __near * and wchar_t __far *. Since all pointers in the Windows API were far pointers (32 bit "fat" pointers - 16 bits for the segment identifier, 16 bits for the actual pointer, i.e. offset from the start of the segment), you had to write char __far * every time (because, based on compiler settings, the implied default might be __near), which makes "LPSTR" start to look reasonable (LP = long-sized pointer, i.e. 32 bit far pointer). But, considering how the C syntax works, you can't easily declare a pointer to a constant string - const LPSTR makes the pointer constant, not the string. So you get LPCSTR. Why have both LP[C]CHAR and LP[C]STR, though? because the former is a pointer to a character, the latter is a pointer a nul-terminated string. For a long time, the compiler couldn't actually tell the difference between the two, but once the compiler started supporting the appropriate annotations, they could be added to the typedef in a perfectly backwards-compatible way

Multiply by two for WCHAR strings (why "WCHAR"? because the compiler might not support wchar_t, and WCHAR in that case would be an alias for unsigned short). How to convince people to upgrade their codebases to wide strings, though? Enter TCHAR and related typedefs, which map to CHAR by default, and WCHAR if UNICODE is #defined, so you can mechanically convert your codebase to TCHAR, then define UNICODE, then fix the issues, then switch to Unicode-only. This multiplies the typedefs by three

Then, remember that on Windows, the C runtime library is just a regular library, not the official platform API, so the whole thing was done a second time for the C runtime. All C string APIs got a wcs counterpart that dealt with wchar_t strings, whether the ANSI standard specified it or not (the non-standard ones were prefixed with an underscore). They also added a _TCHAR typedef, that worked much like the Windows SDK counterpart, except that its definition depended on the _UNICODE #define (as a compiler vendor, Microsoft was allowed to extend the C standard as long as the extensions were prefixed with an underscore), and _tcs macros for all string functions that expanded to either the str or wcs variant based on the presence of _UNICODE (Borland went one step further, and _tcs macros could also expand to _mbcs-prefixed functions, that could deal with char strings in variable-width encodings; the #define was _MULTIBYTE IIRC). The C runtime was spared from the __near vs __far mess, because vendors provided separate C runtime binaries for each memory model, so all pointers in the C runtime could simply be undecorated and use the default width. Windows couldn't have separate binaries for its runtime libraries at the time, and they wouldn't have done it anyway as it would have been considered an extravagant waste of memory. The fact that Windows always used long pointers while the C runtime might not is the reason functions like _lstrlen are part of the Windows API: you couldn't reliably pass a Windows string to strlen/wcslen, because you might have been using a memory model with near pointers, so Windows gave you a small subset of the C string API that always took long pointers as arguments

BSTR and OLESTR are OLE stuff. OLE and the Windows API evolved in parallel (OLE is positively ancient, predating both Win32 and COM), so there's a lot of duplication. OLE 2 in particular always supported Unicode, so OLECHAR always maps to wchar_t (or unsigned char)... on Windows, at least. The Mac and UNIX ports of OLE (used for porting, respectively, Office and Internet Explorer) typedef it to char. OLESTR is a string of OLECHAR and BSTR would appear to be the same thing, but BSTR strings are not just strings of OLECHARs, they are Pascal strings of OLECHARs, with a hidden length field before the first character, and can have embedded null characters. If an API takes a BSTR, you really want to pass a real BSTR, properly allocated and initialized with BSTR functions, and not just a random pointer to an OLECHAR

string and wstring (specializations of template class basic_string) are standard C++ implementations of a dynamically allocated C string, so I wouldn't really count them as separate things. In fact, they work well with Windows character/string types, and a basic_string<TCHAR> can be quite handy (just don't pass a basic_string<OLECHAR> to a BSTR argument!)

_bstr_t is a C++ wrapper for BSTR provided as an extension by the Microsoft C++ runtime. It's automatically pulled in by the Microsoft C++ compiler's COM/OLE support, but it can also be used stand-alone. It's really handy as the BSTR API is a natural fit for this kind of wrapper, and you'd end up writing your own anyway

CString comes from the MFC and/or ATL frameworks, only relevant if you use those frameworks. If you do, they can do a lot to reduce the confusion between all the string types, as they provide handy functions to convert between all of them, regardless of what combination of UNICODE and _UNICODE you're using

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.

boo_radley posted:

A voice whispers in your ear, "MUMPS".

MUMPS has its uses. Next time I need to write a hospital billing system in the 1970s I'll definitely use MUMPS.

Absurd Alhazred
Mar 27, 2010

by Athanatos
I heard MUMPS is coming back because of anti-vaxxers.

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.
anti-VAXers

QuarkJets
Sep 8, 2008

hackbunny posted:

Oh it's easy, they just ignored Unicode for a long time. They never upgraded the API to wchar_t and just toughed it out, requiring conversion of all strings to/from the current encoding until someone came up with a magic universal encoding (UTF-8), and even then it took a long time before it was adoped

Then you have to consider that Windows had to run on 16 bit machines with more than 64 KB of RAM, requiring segmentation: so you not only had char * and wchar_t *, but also char __near *, char __far *, wchar_t __near * and wchar_t __far *. Since all pointers in the Windows API were far pointers (32 bit "fat" pointers - 16 bits for the segment identifier, 16 bits for the actual pointer, i.e. offset from the start of the segment), you had to write char __far * every time (because, based on compiler settings, the implied default might be __near), which makes "LPSTR" start to look reasonable (LP = long-sized pointer, i.e. 32 bit far pointer). But, considering how the C syntax works, you can't easily declare a pointer to a constant string - const LPSTR makes the pointer constant, not the string. So you get LPCSTR. Why have both LP[C]CHAR and LP[C]STR, though? because the former is a pointer to a character, the latter is a pointer a nul-terminated string. For a long time, the compiler couldn't actually tell the difference between the two, but once the compiler started supporting the appropriate annotations, they could be added to the typedef in a perfectly backwards-compatible way

Multiply by two for WCHAR strings (why "WCHAR"? because the compiler might not support wchar_t, and WCHAR in that case would be an alias for unsigned short). How to convince people to upgrade their codebases to wide strings, though? Enter TCHAR and related typedefs, which map to CHAR by default, and WCHAR if UNICODE is #defined, so you can mechanically convert your codebase to TCHAR, then define UNICODE, then fix the issues, then switch to Unicode-only. This multiplies the typedefs by three

Then, remember that on Windows, the C runtime library is just a regular library, not the official platform API, so the whole thing was done a second time for the C runtime. All C string APIs got a wcs counterpart that dealt with wchar_t strings, whether the ANSI standard specified it or not (the non-standard ones were prefixed with an underscore). They also added a _TCHAR typedef, that worked much like the Windows SDK counterpart, except that its definition depended on the _UNICODE #define (as a compiler vendor, Microsoft was allowed to extend the C standard as long as the extensions were prefixed with an underscore), and _tcs macros for all string functions that expanded to either the str or wcs variant based on the presence of _UNICODE (Borland went one step further, and _tcs macros could also expand to _mbcs-prefixed functions, that could deal with char strings in variable-width encodings; the #define was _MULTIBYTE IIRC). The C runtime was spared from the __near vs __far mess, because vendors provided separate C runtime binaries for each memory model, so all pointers in the C runtime could simply be undecorated and use the default width. Windows couldn't have separate binaries for its runtime libraries at the time, and they wouldn't have done it anyway as it would have been considered an extravagant waste of memory. The fact that Windows always used long pointers while the C runtime might not is the reason functions like _lstrlen are part of the Windows API: you couldn't reliably pass a Windows string to strlen/wcslen, because you might have been using a memory model with near pointers, so Windows gave you a small subset of the C string API that always took long pointers as arguments

BSTR and OLESTR are OLE stuff. OLE and the Windows API evolved in parallel (OLE is positively ancient, predating both Win32 and COM), so there's a lot of duplication. OLE 2 in particular always supported Unicode, so OLECHAR always maps to wchar_t (or unsigned char)... on Windows, at least. The Mac and UNIX ports of OLE (used for porting, respectively, Office and Internet Explorer) typedef it to char. OLESTR is a string of OLECHAR and BSTR would appear to be the same thing, but BSTR strings are not just strings of OLECHARs, they are Pascal strings of OLECHARs, with a hidden length field before the first character, and can have embedded null characters. If an API takes a BSTR, you really want to pass a real BSTR, properly allocated and initialized with BSTR functions, and not just a random pointer to an OLECHAR

string and wstring (specializations of template class basic_string) are standard C++ implementations of a dynamically allocated C string, so I wouldn't really count them as separate things. In fact, they work well with Windows character/string types, and a basic_string<TCHAR> can be quite handy (just don't pass a basic_string<OLECHAR> to a BSTR argument!)

_bstr_t is a C++ wrapper for BSTR provided as an extension by the Microsoft C++ runtime. It's automatically pulled in by the Microsoft C++ compiler's COM/OLE support, but it can also be used stand-alone. It's really handy as the BSTR API is a natural fit for this kind of wrapper, and you'd end up writing your own anyway

CString comes from the MFC and/or ATL frameworks, only relevant if you use those frameworks. If you do, they can do a lot to reduce the confusion between all the string types, as they provide handy functions to convert between all of them, regardless of what combination of UNICODE and _UNICODE you're using

Hey thanks for that great explanation, Bill. Hope you're having a good Sunday. How's Melinda? Tell her the thread says hi, have a good day

Taffer
Oct 15, 2010


hackbunny posted:

Oh it's easy, they just ignored Unicode for a long time. They never upgraded the API to wchar_t and just toughed it out, requiring conversion of all strings to/from the current encoding until someone came up with a magic universal encoding (UTF-8), and even then it took a long time before it was adoped

Then you have to consider that Windows had to run on 16 bit machines with more than 64 KB of RAM, requiring segmentation: so you not only had char * and wchar_t *, but also char __near *, char __far *, wchar_t __near * and wchar_t __far *. Since all pointers in the Windows API were far pointers (32 bit "fat" pointers - 16 bits for the segment identifier, 16 bits for the actual pointer, i.e. offset from the start of the segment), you had to write char __far * every time (because, based on compiler settings, the implied default might be __near), which makes "LPSTR" start to look reasonable (LP = long-sized pointer, i.e. 32 bit far pointer). But, considering how the C syntax works, you can't easily declare a pointer to a constant string - const LPSTR makes the pointer constant, not the string. So you get LPCSTR. Why have both LP[C]CHAR and LP[C]STR, though? because the former is a pointer to a character, the latter is a pointer a nul-terminated string. For a long time, the compiler couldn't actually tell the difference between the two, but once the compiler started supporting the appropriate annotations, they could be added to the typedef in a perfectly backwards-compatible way

Multiply by two for WCHAR strings (why "WCHAR"? because the compiler might not support wchar_t, and WCHAR in that case would be an alias for unsigned short). How to convince people to upgrade their codebases to wide strings, though? Enter TCHAR and related typedefs, which map to CHAR by default, and WCHAR if UNICODE is #defined, so you can mechanically convert your codebase to TCHAR, then define UNICODE, then fix the issues, then switch to Unicode-only. This multiplies the typedefs by three

Then, remember that on Windows, the C runtime library is just a regular library, not the official platform API, so the whole thing was done a second time for the C runtime. All C string APIs got a wcs counterpart that dealt with wchar_t strings, whether the ANSI standard specified it or not (the non-standard ones were prefixed with an underscore). They also added a _TCHAR typedef, that worked much like the Windows SDK counterpart, except that its definition depended on the _UNICODE #define (as a compiler vendor, Microsoft was allowed to extend the C standard as long as the extensions were prefixed with an underscore), and _tcs macros for all string functions that expanded to either the str or wcs variant based on the presence of _UNICODE (Borland went one step further, and _tcs macros could also expand to _mbcs-prefixed functions, that could deal with char strings in variable-width encodings; the #define was _MULTIBYTE IIRC). The C runtime was spared from the __near vs __far mess, because vendors provided separate C runtime binaries for each memory model, so all pointers in the C runtime could simply be undecorated and use the default width. Windows couldn't have separate binaries for its runtime libraries at the time, and they wouldn't have done it anyway as it would have been considered an extravagant waste of memory. The fact that Windows always used long pointers while the C runtime might not is the reason functions like _lstrlen are part of the Windows API: you couldn't reliably pass a Windows string to strlen/wcslen, because you might have been using a memory model with near pointers, so Windows gave you a small subset of the C string API that always took long pointers as arguments

BSTR and OLESTR are OLE stuff. OLE and the Windows API evolved in parallel (OLE is positively ancient, predating both Win32 and COM), so there's a lot of duplication. OLE 2 in particular always supported Unicode, so OLECHAR always maps to wchar_t (or unsigned char)... on Windows, at least. The Mac and UNIX ports of OLE (used for porting, respectively, Office and Internet Explorer) typedef it to char. OLESTR is a string of OLECHAR and BSTR would appear to be the same thing, but BSTR strings are not just strings of OLECHARs, they are Pascal strings of OLECHARs, with a hidden length field before the first character, and can have embedded null characters. If an API takes a BSTR, you really want to pass a real BSTR, properly allocated and initialized with BSTR functions, and not just a random pointer to an OLECHAR

string and wstring (specializations of template class basic_string) are standard C++ implementations of a dynamically allocated C string, so I wouldn't really count them as separate things. In fact, they work well with Windows character/string types, and a basic_string<TCHAR> can be quite handy (just don't pass a basic_string<OLECHAR> to a BSTR argument!)

_bstr_t is a C++ wrapper for BSTR provided as an extension by the Microsoft C++ runtime. It's automatically pulled in by the Microsoft C++ compiler's COM/OLE support, but it can also be used stand-alone. It's really handy as the BSTR API is a natural fit for this kind of wrapper, and you'd end up writing your own anyway

CString comes from the MFC and/or ATL frameworks, only relevant if you use those frameworks. If you do, they can do a lot to reduce the confusion between all the string types, as they provide handy functions to convert between all of them, regardless of what combination of UNICODE and _UNICODE you're using

whycppisadisaster.txt

Absurd Alhazred
Mar 27, 2010

by Athanatos

Taffer posted:

whycppisadisaster.txt

None of this really has to do with C++, though. It's Windows API, you can live blissfully unaware of this nonsense until you have to make a direct Win32 call, and even then you won't run into most of these, or they're hidden behind convenience macros.

Beamed
Nov 26, 2010

Then you have a responsibility that no man has ever faced. You have your fear which could become reality, and you have Godzilla, which is reality.


Taffer posted:

whycppisadisaster.txt

Did you not read the post, or?

Nude
Nov 16, 2014

I have no idea what I'm doing.

Absurd Alhazred posted:

you can live blissfully unaware

Pretty good summary of how I code to be honest.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

hackbunny posted:

Windows couldn't have separate binaries for its runtime libraries at the time, and they wouldn't have done it anyway as it would have been considered an extravagant waste of memory.

OK I think this part may not make much sense, actually, in that I doubt you could make a DLL that takes near pointer arguments for its functions. On the other hand, UNIX did let you statically link to the system libraries, and Windows could have done the same. But it didn't because of, I suspect, inter-process fuckery requirements, which probably were only part of the design because the extremely low memory footprint demanded DLLs loaded in shared memory, which in turn enabled inter-process fuckery, the two horrible things circularly justifying each other (and causing endless grief for the people who had to port Windows to the Windows NT kernel, and a long tail of security vulnerabilities that still isn't over)

hackbunny fucked around with this message at 02:31 on Jun 11, 2018

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Athas posted:

Unix is even older than Windows, so how come the POSIX API is (relatively speaking) so much simpler?

It's not. Popular UNIXen of the day (IRIX / Tru64 / HP/UX / IBM AIX) had wacky Unicode support that mirrors what you see in the Windows API. When the POSIX effort started in the late 90s, they were basically tossed out the window in favor of just not using Unicode. Even in POSIX, the locale system (LANG, LC_ALL, etc.) is probably one of the gnarliest and worst parts. The infamous C.utf8 locale is not a standard of any sort, it's a Linux-ism.

All of this still causes headaches today.

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.
Hi everyone! It's Monday so I guess there must be a new node vulnera....

yep

The source code of node-macaddress posted:

exec("cat /sys/class/net/" + iface + "/address", function (err, out) {

Ofcourse the people looking at these security disclosures can't reach the original maintainer since he probably went on to program in golang, but good news:

Hackerone posted:

Doesn't look epic to me, also last publish was 3 years ago.

Thankfully it doesn't look epic, it only has 1,325,674 weekly downloads so I guess nobody's using it.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
And naturally a HN poster sees nothing wrong with a function for getting the MAC address for a network interface allowing arbitrary code execution:

quote:

I hate to be an apologist for this kind of thing, but this vulnerability is in the same time zone to me as saying mysql2 has a critical vulnerability if attackers get access to connection.query's first argument.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Taffer posted:

whycppisadisaster.txt

Yeah you're not wrong. C++ does have a standard string type and a standard memory allocator, but everyone, rightly or wrongly, seems to find reasons to make their own special snowflake ones. Other languages simply don't give you a choice and are better (for a certain measure of "better") for it

Presto
Nov 22, 2002

Keep calm and Harry on.

feedmegin posted:

Invent ur own plang imo. Mine is a cross of statically typed and compiled Python
Good, I like tha....

quote:

and Pascal :sun:
never mind.

Absurd Alhazred
Mar 27, 2010

by Athanatos
I miss Pascal. :smith:

Mooey Cow
Jan 27, 2018

by Jeffrey of YOSPOS
Pillbug

hackbunny posted:

Yeah you're not wrong. C++ does have a standard string type and a standard memory allocator, but everyone, rightly or wrongly, seems to find reasons to make their own special snowflake ones. Other languages simply don't give you a choice and are better (for a certain measure of "better") for it

All that WinAPI stuff is C though, written long before there even was a C++ standard, and any new stuff has to be backwards compatible with that. If they could rewrite it all from scratch using actual C++ hopefully they would use the standard library and UTF-8 (or at least one consistent encoding for everything). They would have to come up with a canonical C++ ABI though, so it would at least work across DLL boundaries, which is currently pretty difficult and requires everything to be compiled with exactly the same settings on exactly the same compiler.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Mooey Cow posted:

All that WinAPI stuff is C though, written long before there even was a C++ standard, and any new stuff has to be backwards compatible with that. If they could rewrite it all from scratch using actual C++ hopefully they would use the standard library and UTF-8 (or at least one consistent encoding for everything). They would have to come up with a canonical C++ ABI though, so it would at least work across DLL boundaries, which is currently pretty difficult and requires everything to be compiled with exactly the same settings on exactly the same compiler.

Other languages do this just fine :shrug: They're just like "this is your string type, this is your allocator type, now gently caress off". But C or C++? It's all "my business case absolutely requires custom everything"

Adbot
ADBOT LOVES YOU

Absurd Alhazred
Mar 27, 2010

by Athanatos

Mooey Cow posted:

All that WinAPI stuff is C though, written long before there even was a C++ standard, and any new stuff has to be backwards compatible with that. If they could rewrite it all from scratch using actual C++ hopefully they would use the standard library and UTF-8 (or at least one consistent encoding for everything). They would have to come up with a canonical C++ ABI though, so it would at least work across DLL boundaries, which is currently pretty difficult and requires everything to be compiled with exactly the same settings on exactly the same compiler.

If you use the managed-code based (C# and such) API, it's much more modern. But that has its own overhead.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply