1

I'm trying to add proper error reporting to a legacy C++ Win32 DLL, after not having programmed in C++ for more than a decade.

This has been a forcible reminder of the incredible tedium of working with null terminated strings in C/C++ - not to mention the potential buffer overrun and security problems.

I'm considering using a more advanced string library - maybe MFC CString or the STL library.

Edit

DLL is used by both older versions of our software - written in C++; and newer versions - written in C#.

Compiler is VS2008.

For the first pass, I'm logging to the standard Windows Event Log, because passing error messages back to the DLLs clients will be a big architectural change (current architecture is terrible, with multiple failure modes being collapsed into a single boolean pass/fail return value that is passed all the way back up the call stack. Needless to say, this makes problem diagnoses a nightmare). But I'll want to improve this at some later date.

String Library Questions

Since this is a DLL, is this even a good idea?

Are there any special considerations for DLLs?

Gotchas I should be aware of?

Is one library better than the other for this purpose?

Null String Questions

If I'm stuck with null terminated, which set of string functions should I be using? The MS help docs discourage the use of the old C functions (e.g. strcat, etc). But there seem to be many, many other options available now (e.g. _tcscat, _mbscat, wcscat, etc). Which should I use, and why?

Tom Bushell
  • 5,865
  • 4
  • 45
  • 60
  • What version of the VC++ compiler are you using? As @Remy noted, how and where the error reports are consumed is the most important issue here. Have you considered an existing infrastructure like log4cpp? – Steve Townsend Apr 19 '12 at 13:31
  • I would take a look at log4cpp. There is a Windows Event Log appender built in and you can easily convert later (or use multiple appenders). This is a more important decision cost-wise than how you decide to handle char* in the existing code, to me. You can tackle that when you need to have your client apps consume the log data directly, with associated marshalling issues across C++/C# clients. For now it sounds like quickly adding issue debug info is the priority. – Steve Townsend Apr 19 '12 at 15:26

3 Answers3

3

It really depends on what kind of error reporting you want to add, and whether that reporting is just inside the DLL or if it crosses the DLLL boundary into the calling EXE. You can use whatever string classes/libraries you want INSIDE the DLL's internal code, but for parameters of exported DLL functions and callbacks, you should keep using null-terminated character pointers for compatibility with multiple compilers and languages.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
3

Sharing any kind of template class from a DLL is dangerous. Since the template is in the header files, you have no control over whether the program is using the same versions of the header as your DLL - a mismatch can lead to deadly bugs.

As for the differences between _tcscat, _mbscat, and wcscat, you'll need to decide on a character set for your API. The _mb functions use the mostly obsolete multi-byte character sets, and the wc functions use wchar_t Unicode. The _t functions will resolve to one or the other depending on how you set up your project definitions.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Thanks for the warning. I also found the related question "Returning Strings from DLL Functions" http://stackoverflow.com/q/4446620/102554 very informative on this kind of issue. – Tom Bushell Apr 19 '12 at 15:24
  • WRT to the _t functions, do I have to make sure that the project definitions are the same for both the DLL project and the client projects? Where are these project settings in the VS IDE? – Tom Bushell Apr 19 '12 at 15:31
  • @TomBushell, if you get a mismatch in the project settings for the DLL and client you'll get link errors as the function signatures won't match either. You can find the setting under Configuration Properties.General.Character Set. – Mark Ransom Apr 19 '12 at 16:02
1

If you're careful you can always convert anything incoming using the std::string constructor, and convert anything outgoing with str.c_str().

orlp
  • 112,504
  • 36
  • 218
  • 315
  • Do you think std::string is a better choice than MFC CString? A quick browse through related questions leads me to believe more people are using std::string. – Tom Bushell Apr 19 '12 at 15:44
  • @TomBushell, `std::string` is the standard and I'd use it in all cases unless there's a good reason not to. Or maybe in this case `std::wstring` for Windows Unicode support, it's in the standard too. – Mark Ransom Apr 19 '12 at 16:06
  • I just discovered that our legacy C++ MFC clients use CString, so I have a slight bias towards using that in the DLLs as well - just to be consistent. But the consensus seems to be that using char * at the DLL boundary is the best approach. – Tom Bushell Apr 19 '12 at 17:56