C++/Win32 deprecated string functions: mbstowcs, wcstombs, safe or not safe? - c++

The compiler (VC 2010) keeps complaining about me using them.
In case not safe, please offer simplest replacement.

Well you have the safe versions of most common string functions, they end at _s and offer a possibility to specify the length of the buffer.

If by "safe" you mean that you can use the functions without worrying that they will disappear in the future? In that case, most likely yes, as these functions are part of the C (and C++ probably) standard.

Many Windows DLLs use (imports, exports) these unsafe (also called "obsolete" or "banned") APIs. These are parts of Win32!

I used them in win-32 GDI+ string-drawing functions which takes a char array then chages into wide char string then draw on screen. I use VC++ 2010 express too! Works without any leak.

Related

Problem passing std::string though DLL boundaries with visual studio

I have a DLL that contains some code like this:
class Info {
int a
int b
int c
std::string str1;
std::string str2;
};
__declspec(dllexport) class C {
Info getInfo();
}
I compile this code with Visual Studio 2015, and calling C::getInfo() works perfectly fine on my system.
Now somebody else is trying to use the DLL, and he's also using Visual Studo 2015. The call goes well but the strings don't contain any accessible data. Even the debugger reports "Error reading characters of string", and the program crashes when trying to read it.
There was also a similar problem with std::vector which I could solve by inlining the code that created the vector.
To me this looks like either the other person is using a different STL version, or the compiler somehow produces a different memory layout for std::string (though he claims to use default settings).
Is this possible? I saw there are different updates for VS 2015 and we might not have the same updates installed.
Any recommendations for fixing this? I can't move to char* without significantly breaking the API. Most users don't even use Visual Studio (or Windows), so this hasn't been a problem until now.
That's life I'm afraid. Unless you have exactly the same compiler (including C++ Standard Library) and compiler settings, this is not guaranteed to work. I'm not convinced from a C++ Standards perspective that even this is guaranteed to work. It's pretty nigh on impossible to build an ABI in C++. In your specific example, there's no guarantee that the struct will be built with the same alignment characteristics. sizeof(std::string) varies considerably due in part to short string optimisations which can even be compiler-configurable.
Alternatives:
Use C linkage for your exported functions and char*-style interfaces that are allocated and deallocated by the caller (cf. the Windows API). (Don't ever allocate memory in the client and deallocate in the dll, and vice-versa.)
Make sure the user of your library can build it from the source files. Consider distributing as a static library rather than a dynamic one, as the former are a little easier to work with.

What is the equivalent standard function of the "AfxIsValidAddress" function?

I was using an MFC-project, that shall be proted in a platform-independent environment, using std-function instead of MFC/AFX.
For example: instead CString the std::string, instead CMutex the std::mutex will be used.
What is the platform-independet, C++11 std::-equivalent of the MFC function "AfxIsValidAddress"?
There is not something similar to AfxIsValidAddress() in the standard library and it appears that the function doesn't actually do that much validation anyway.
See AfxIsValidAddress (and Others) Don’t Work as Advertised which says the function ends up just doing a check against NULL. It also has this to say about the family of valid address check functions:
There are several Win32 API similar in functionality: IsBadWritePtr,
IsBadHugeWritePtr, IsBadReadPtr, IsBadHugeReadPtr, IsBadCodePtr,
IsBadStringPtr. It has been known since at least 2004 that these
functions are broken beyond repair and should never be used. The
almighty Raymond Chen and Larry Osterman both discuss the reasons in
detail, so just a short rehash: IsBad*Ptr all work by accessing the
tested address and catching any thrown exceptions. Problem is that a
certain few of these access violations (namely, those on stack guard
pages) should never be caught – the OS uses them to properly enlarge
thread stacks.
I think it is better to just follow standard C++ procedures to check that a pointer is not a nullptr or better yet to limit the use of pointers as much as possible.

Array of char or std::string for a public library?

my question is simple:
Should I use array of char eg:
char *buf, buf2[MAX_STRING_LENGTH]
etc or should I use std::string in a library that will be used by other programmers where they can use it on any SO and compiler of their choice?
Considering performance and portability...
from my point of view, std strings are easier and performance is equal or the difference is way too little to not use std:string, about portability I don't know. I guess as it is standard, there shouldn't be any compiler that compiles C++ without it, at least any important compiler.
EDIT:
The library will be compiled on 3 major OS and, theorically, distributed as a lib
Your thoughts?
ty,
Joe
Depends on how this library will be used in conjunction with client code. If it will be linked in dynamically and you have a set of APIs exposed for the client -- you are better off using null terminated byte strings (i.e. char *) and their wide-character counterparts. If you are talking about using them within your code, you certainly are free to use std::string. If it is going to be included in source form -- std::string works fine.
But if your library is shipped as DLL your users will have to use the same implementation of std::string. It won't be possible for them to use STLPort (or any other implementation) if your library was built using Microsoft STL.
As long as you are targetting pure C++ for your library, using std::string is fine and even desirable. However, doing that ties you to a particular implementation of C++ (the one used to build your library), and it can't be linked with other C++ implementations or other languages.
Often, it is highly desirable to give a library a C interface rather than a C++ one. That way its usable by any other language that provides a C foreign function interface (which is most of them). For a C interface, you need to use char *
I would recommend just using std::string. Besides if you want compatibility with libraries requiring C-style strings (for example, which uses a C compatible API), you can always just use the c_str() method of std::string.
In general, you will be better off using std::string, certainly for calls internal to your library.
For your API, it's dependent on what its purpose is. For internal use within your organization, an API that uses std::string will probably be fine. For external use you may wish to provide a C API, one which uses char*

strcmpi renamed to _strcmpi?

In MSVC++, there's a function strcmpi for case-insensitive C-string comparisons.
When you try and use it, it goes,
This POSIX function is deprecated beginning in Visual C++ 2005. Use the ISO C++ conformant _stricmp instead.
What I don't see is why does ISO not want MSVC++ to use strcmpi, and why is _stricmp the preferred way, and why would they bother to rename the function, and how is a function beginning with an underscore ISO conformant. I know there must be a reason for all this, and I'm suspecting its because strcmpi is non-standard, and perhaps ISO wants non-standard extensions to begin with an _underscore?
ISO C reserves certain identifiers for future expansion (see here), including anything that starts with "str".
IMNSHO, this is Microsoft's way of saying "Do not put Unix software on Windows machines". There are several frustrating aspects to the problem:
strcmpi() is not a POSIX function - the relevant functions are defined in <strings.h> and are called strcasecmp() etc.
Even if you explicitly request support for POSIX functions, Microsoft thinks that you may not use the POSIX names but must prefix them with the wretched underscore.
AFAIK, there isn't a way of overriding the MSVC compiler's view on the issue.
That said, the GCC tool chain gets a bit stroppy about some functions - mktemp() et al. However, it does compile and link successfully, despite the warnings (which are justified).
I note that MSVC also has a bee in its bonnet about snprintf() et al. If their function conformed to the C99 standard (along with the rest of the compiler), then there would never be any risk of an overflow - the standard requires null termination, contrary to the claims of Microsoft.
I haven't got a really good solution to this problem - I'm not sure there is one. One possibility is to create a header (or set of headers) to map all the actual POSIX names to Microsoft's misinterpretation of them. Another is two create a library of trivial functions with the correct POSIX name that each call down onto the Microsoft version of the name (giving you a massive collection of four-line functions - the declarator line, an open brace, a close brace, and a return statement that invokes the Microsoft variant of the POSIX function name.
It's funny how the Microsoft API calls, which also pollute the user's name space, are not deprecated or renamed.
Names begining witth an underscore and a lower case letter are reserved by the C++ Standard for the C++ implementation, if they are declared in the global namespace. This stops them from clashing with similar names in your own code, which must not use this naming convention.
strcmpi goes away altogether in Visual C++ 2008, so you should definitely heed the deprecation if you ever intend to upgrade.
The _ doesn't make the function ISO standard, it's just that functions beginning with _ are safer to add as the language evolves because that's one of the parts of the namespace reserved for the language to use.
According to Microsoft's documentation for _stricmp, it sounds like strcmpi has some practices that result in some unintuitive orderings (including normalizing to lower case instead of simply treating case as irrelevant). Sounds like _stricmp takes more pains to do what one would naturally expect.

How do you handle strings in C++?

Which is your favorite way to go with strings in C++? A C-style array of chars? Or wchar_t? CString, std::basic_string, std::string, BSTR or CComBSTR?
Certainly each of these has its own area of application, but anyway, which is your favorite and why?
std::string or std::wstring, depending on your needs. Why?
They're standard
They're portable
They can handle I18N
They have performance guarantees (as per the standard)
Protected against buffer overflows and similar attacks
Are easily converted to other types as needed
Are nicely templated, giving you a wide variety of options while reducing code bloat and improving performance. Really. Compilers that can't handle templates are long gone now.
A C-style array of chars is just asking for trouble. You'll still need to deal with them on occasion (and that's what std::string.c_str() is for), but, honestly -- one of the biggest dangers in C is programmers doing Bad Things with char* and winding up with buffer overflows. Just don't do it.
An array of wchar__t is the same thing, just bigger.
CString, BSTR, and CComBSTR are not standard and not portable. Avoid them unless absolutely forced. Optimally, just convert a std::string/std::wstring to them when needed, which shouldn't be very expensive.
Note that std::string is just a child of std::basic_string, but you're still better off using std::string unless you have a really good reason not to. Really Good. Let the compiler take care of the optimization in this situation.
std::string !!
There's a reason why they call it a "Standard".
basic_string is an implementation detail and should be ignored.
BSTR & CComBSTR only for interOp with COM, and only for the moment of interop.
std::string unless I need to call an API that specifically takes one of the others that you listed.
Here's an article comparing the most common kinds of strings in C++ and how to convert between them. Unraveling Strings in Visual C++
If you can use MFC, use CString. Otherwise use std::string. Plus, std::string works on any platform that supports standard C++.
When I have a choice (I usually don't), I tend to use std::string with UTF-8 encoding (and the help of UTF8 CPP library. Not that I like std::string that much, but at least it is standard and portable.
Unfortunatelly, in almost all real-life projects I've worked on, there have been internal string classes - most of them actually better than std::string, but still...
I am a Qt dev, so of course I tend to use QString whenever possible :).
It's quite nice: unicode compliant, thread-safe implicit-sharing (aka copy-on-write), and it comes with an API designed to solve practical real-world problems (split, join, replace (with and without regex), conversion to/from numbers...)
If I can't use QString, then std::wstring. If you are stuck with C, I recommend glib GString.
I use std::string (or basic_string<TCHAR>) whenever I can. It's quite versatile (just like CStringT), it's type-safe (unlike printf), and it's available on every platform.
Other, std::wstring.
std::string is 20th century technology. Use Unicode, and sell to 6 billion people instead of 300 milion.
C-style char arrays have their place, but if you use them extensively you are asking to waste time debugging off by one errors. We have our own string class tailored for use in our (embedded development environment).
We don't use std::string because it isn't always available for us.
If you're using MFC, use CString. Otherwise I agree with most of the others, std::string or std::wstring all the way.
Microsoft could have done the world a huge favor by adding std::basic_string<TCHAR> overloads in their latest update of MFC.
I like to use TCHAR which is a define for wchar or char according to the projects settings.
It's defined in tchar.h where you can find all of the related definitions for functions and types you need.
std::string and std::wstring if I can, and something else if I have to.
They may not be perfect, but they are well tested, well understood, and very versatile. They play nicely with the rest of the standard library which is also a huge bonus.
Also worth mentioning, stringstreams.
std::string is better than nothing, but it's annoying that it's missing basic functionality like split, join and even a decent format call...
Unicode is the future. Do not use char* and std::string. Please )
I am tired of localization bugs.