Click here to Skip to main content
Click here to Skip to main content

Keeping It Clean - String Function Wrappers for VS2005

By , 17 Nov 2006
 

Introduction

I have to maintain code that was originally written during the heyday of Visual Studio 6.0, but that also needs to be used in newer projects that are compiled under Visual Studio 2005. The files in question are shared between two programming teams - one is writing VC6 code, and the other is writing VS2005 code - the projects are different but we're all about code re-use. I'm sure there are at least three other people out there in CP-land that have the same requirements.

Specifically, our code invariably includes the use of several standard I/O functions like sprintf, printf, et al, and we all know what happens when you try to use these functions in VS2005 - the compiler pukes out hundreds (or thousands) of warnings about the functions being deprecated. The quick fix is to include the appropriate preprocessor definition in the program settings, but that's just plain laziness.

How I Solved The Problem

My technique was to write a wrapper function that will use the appropriate version of the stdio function, depending on what version of the compiler you're using. This really cleaned up my code in terms of readability because the preprocessor code is all in one place instead of being scattered through the code (about 50 instances in just one file).

// Determine which compiler we're using.  For versions PRIOR to 2005, we use 
// the old ("unsecure" - guffaw) string functions that VS2005 pukes up
// warnings on.  This presents quite the pain in the butt when you're trying  
// to write code supported by multiple versions of Visual C.

#define _VS2005_
#if _MSC_VER < 1400
    #undef _VS2005_
#endif

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
int sprintf_ex(char* sDest, int nSize, char* sFormat, ...) 
{
    va_list argList;
    va_start(argList, sFormat);
    int nCount = 0;

#ifdef _VS2005_
    nCount = _vsnprintf_s(sDest, nSize, nSize-1, sFormat, argList);
#else
    nCount = _vsnprintf(sDest, nSize, sFormat argList);
#endif
    va_end(argList);

    return nCount;
}

Implementation might look like this:

    char sTest[1024];
    int nCount = sprintf_ex(sTest, sizeof(sTest), "%d %s", 5, "Test");

It would be a simple exercise to wrap other functions in a similar fashion, but since we didn't have a need, I didn't write the code. This should be a simple exercise for most C++ programmers, given the example above.

What?! No Sample Code To Download?!!!

Oh please. As you can see, it's just a function wrapper that demonstrates a simple technique. I'm not going to go through the hassle of preparing a sample project for something that you simply have to copy/paste into an existing source file to try out. Besides, you're all supposed to be programmers - create a test project if you have to.

What?! No Screen Shots To Gawk At?!?!

You guys are funny. Now it's my turn to be funny.

Disclaimer

I do not code in managed C++, so I don't know if this will work in that environment.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

John Simmons / outlaw programmer
Software Developer (Senior)
United States United States
Member
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.
 
My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralI really like this article.memberWong Shao Voon4 Dec '06 - 15:13 
This article came at the right time while I was writing this article(below).
 
http://www.codeproject.com/string/StringFormatNative.asp
 
I was thinking how to support the original C functions and the new Safe C functions of VC8 in the same source files. The #defines is a timely help. Thanks!
GeneralWait a minute, use the defines to eliminate warnings...memberJason King20 Nov '06 - 15:03 
http://msdn2.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx
GeneralRe: Wait a minute, use the defines to eliminate warnings...memberJohn Simmons / outlaw programmer21 Nov '06 - 1:58 
THIS ARTICLE IS NOT ABOUT ELIMINATING WARNINGS IN VS2005!
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Wait a minute, use the defines to eliminate warnings...memberColin Angus Mackay22 Nov '06 - 10:47 
If you eliminate the warnings you could hide other problems that you won't know about until they bite you on the arse.
 
I try and think of a warning as the compiler saying that it will compile the code, but there exists some problem which you should really clear up. I actually elevate some warnings to errors becuase I know that they will cause some real problems in the future if it isn't resolved. By problems, mostly I mean inadvertant bugs at run time. I'm a great believer in getting the compiler to catch as many problems as possible.
 

Upcoming Scottish Developers events:
* We are starting a series of events in Glasgow in 2007. Are you interested in a particular subject, or as a speaker?
* Developer Day Scotland: are you interested in speaking or attending?

 
My: Website | Blog | Photos

GeneralRe: Wait a minute, use the defines to eliminate warnings...memberJason King22 Nov '06 - 11:35 
It depends upon what you are doing. For example, I work on cross platform programs where the other compilers and libraries use the more standard naming convention. So, the options are either to disable the warning (I prefer the defines method as opposed to the pragma option) or to use a system similar to John Simmon's article. We have no interest in building alternative function call wrappers - if we do not have to. And Microsoft supplied a way to avoid the warning because they understood the implications of the name change.
GeneralRe: Wait a minute, use the defines to eliminate warnings...memberColin Angus Mackay22 Nov '06 - 11:45 
Jason King wrote:
It depends upon what you are doing.

 
You're right - of course. Everything should be examined on its merits. My general rule is not to disable any warnings. But having said that today put an email round the development team where I work with a good case for disabling one of the warnings Visual Studio Team System Code Analysis was producing. (So, now I've just realised that I've shot my own argument in the foot - damn!) It isn't something I do lightly because for the most part warnings are there for a good reason.
 

Upcoming Scottish Developers events:
* We are starting a series of events in Glasgow in 2007. Are you interested in a particular subject, or as a speaker?
* Developer Day Scotland: are you interested in speaking or attending?

 
My: Website | Blog | Photos

GeneralRe: Wait a minute, use the defines to eliminate warnings...memberJohn Simmons / outlaw programmer23 Nov '06 - 15:30 
If it's your own code throwing the warning, there are *very* few valid reasons to just pragma around it.
 
But like I said before, that's *not* what this article is about.
 
This article is about sharing code with legacy MS compilers which don't have the new prototypes.
 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralNot shure abount the needmemberemilio_grv19 Nov '06 - 22:21 
Cosidering the declaring the CRT functions deprecated for safety is a MS initiative that is controversed in the C++ community, and the MS itself is rethinking about, why not just disable the useless warnings ?
It's easy:
// disable non-sense warning
#pragma warning(disable: 4100) //unreferenced formal parameter
#pragma warning(disable: 4996) //nonsense "deprecated" MS initiative
#pragma warning(disable: 4512) //unassignable object are by design
#pragma warning(disable: 4345) //POD default initialization

 

2 bugs found.
> recompile ...
65534 bugs found.
D'Oh! | :doh:

GeneralRe: Not shure abount the needmemberJohn Simmons / outlaw programmer20 Nov '06 - 0:19 
emilio_grv wrote:
why not just disable the useless warnings ?

 
Because disabling warnings could potentially mask other subtle problems in your code. Granted, there are some warnings that simply aren't addressable via source code, and using pragma to get a clean compile is necessary, but this is most certainly not one of those cases.
 
Also:
 
1) This article is more for the VS2005 guys that need to share source code with VC6 guys.
 
2) This article is NOT about getting rid of warnings in VS2005.

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Not shure abount the needmemberemilio_grv20 Nov '06 - 20:56 
I'm sorry, but I don't get the point:
Which subtle bug should I loose if I disable the C4996 that is a specific warning about CRT (That its up to me to decide to use) intruduced by Microsoft only and only in C++8 that will probably disappear in C++8.1 ?
 
If I'm warned about something is perfectly normal, i'm not warned. Just spammed(!)

 

2 bugs found.
> recompile ...
65534 bugs found.
D'Oh! | :doh:

GeneralRe: Not shure abount the needmemberJohn Simmons / outlaw programmer21 Nov '06 - 1:56 
THIS ARTICLE IS NOT ABOUT ELIMINATING WARNINGS IN VS2005!

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Not shure abount the needmemberWalderMort22 Nov '06 - 7:43 
emilio_grv wrote:
(That its up to me to decide to use)

 
That is exactly the point, it's up to YOU to decide. Some of us other programers would also like the choice.
 
Personaly I only ever disable a warning if I feel there is no other way, even when doing so, I re-enable the warning directly after the line in question. Making a habit of this will not only help you find bugs, but help eliminate them in the first place.
GeneralRe: Not shure abount the needmemberemilio_grv23 Nov '06 - 2:09 
Yep, that's exacly my point:
to stay with John (the author), the situation is:
There is a thing (CRT) in VC6 that has a function named strcpy
That same thing, in VC8 is still named strcpy. But the compiler is instructed to say “thst’s “deprecated” (note the the use of the wor d”deprecated in incorrecti in this sense)
Another new function, named strcpy_s (but with different parameters) had been introduced.
 
My point is: the two function are not one the replacement fort the other. They are different, since they suppose I have a different way to track buffer lengths.
I can agree that the second is safer than the first, but I cannot use the second where the code was not supposed to use it.
 
Now, John (correct me if I misunderstood) says: I told my team, when developing NEW code, to code respecting the “_s” paradigm, and –when they are required to use old platforms- I give them some wrappers that expose the new prototype, but fall through the old implementation. (In fact , he use two distinct implementation of a same wrapper). So my coders will always take care of the buffer length. Simply, the old platform doesn’t do the checks.
 
What I’m saying is a different thing:
Someone wants me to know that a more safe function exist to do a job. I know it, but I want –for some reason- to still use the old one, for example, when porting the old code in the new implementation.
In that case, more than a wrapper, I just need do disable the warning, since the problem it’s not the code (whose correctness is supposed to be proven), but the warning itself (that’s talking about something is not required, in that context), warning me about a problem that I know for sure it doesn’t exist.
 
Hence, I disable it and re-enable it when the point when I’m sure about is over.
 

 

2 bugs found.
> recompile ...
65534 bugs found.
D'Oh! | :doh:

GeneralQuestion [modified]memberS Douglas19 Nov '06 - 18:18 
The only thing missing from the article is Visual Studio Version values (as I'm too lazy to look them up Blush | :O ).
 
What is the version number for VS6.0, VS2002, VS2003 & VS2005?
 
I realize this is slightly out of scope for the article but your article is all about dealing with different versions of Visual Studio & its related complier.

Little hunting around the MSDN here is then version info
_MSC_VER
1400 = VS 8.0 / VS 2005
1310 = VS 7.1 / VS 2003
1300 = VS 7.0 / VS 2002
1200 = VS 6.0
 
-- modified at 4:57 Monday 20th November, 2006
 


I'd love to help, but unfortunatley I have prior commitments monitoring the length of my grass. :Andrew Bleakley:


GeneralRe: QuestionmemberJohn Simmons / outlaw programmer20 Nov '06 - 0:12 
Within the context of this article, the other version numbers don't matter. MSC versions prior to 1400 don't have the "secure" prototypes defined.
 

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: QuestionmemberS Douglas20 Nov '06 - 1:34 
John Simmons / outlaw programmer wrote:
Within the context of this article, the other version numbers don't matter.

 
Fair enough.
 


I'd love to help, but unfortunatley I have prior commitments monitoring the length of my grass. :Andrew Bleakley:


GeneralSuggestionsmemberRedFraggle17 Nov '06 - 7:14 

#ifdef _VS2005_
int sprintf_ex(char* sDest, int nSize, char* sFormat, ...)
{
va_list argList;
va_start(argList, sFormat);
int nCount = 0;
nCount = _vsnprintf_s(sDest, nSize, nSize-1, sFormat, argList);
va_end(argList);
 
return nCount;
}
#else
#define sprintf_ex _vsnprintf(sDest, nSize, sFormat argList);
#endif

above should be more performant (for VS 2003)
but maybe one would prefer something like:
#ifndef _VS2005_ //not deffed? add function
int _vsnprintf_s(char* sDest, int nSize,int doesnotexistin2003, char* sFormat, ...)
{
va_list argList;
va_start(argList, sFormat);
int nCount = 0;
nCount = _vsnprintf(sDest, nSize, sFormat argList);
va_end(argList);
return nCount;
}
#endif

 
first example 'spoils' only VS2005 with some 'overhead', second one 'only' 2003 (there migth be still something left to optimize Wink | ;)
GeneralRe: SuggestionsmemberJohn Simmons / outlaw programmer17 Nov '06 - 9:52 
That's certainly another way to do it. Smile | :)

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

QuestionRe: SuggestionsmemberKarstenK19 Nov '06 - 21:33 
I have found the _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES macro which does this work in all possible cases. Is it less worth for this task?
 

 
Greetings from Germany

AnswerRe: SuggestionsmemberJohn Simmons / outlaw programmer20 Nov '06 - 0:09 
I didn't do this as much for me (using VS2005) as I did for the other team using VC6. It's an admitted pain in the ass, but I'd rather write code that compiles clean without the need for shortcut macros. To each his own. You certainly aren't required to use this technique, and there have been a couple of other methods suggested in other messages.
 

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralGot my 5memberJim Crafton17 Nov '06 - 5:03 
I gave you a five just for the Disclaimers!
 
¡El diablo está en mis pantalones! ¡Mire, mire!
 
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
 
SELECT * FROM User WHERE Clue > 0
0 rows returned

Save an Orange - Use the VCF!
Techno Silliness

GeneralWould be better to wrap it Unicode-compliantlyeditorNishant Sivakumar17 Nov '06 - 4:40 
Instead of wrapping _vsnprintf_s/_vsnprintf, you could wrap _vsntprintf_s/_vsntprintf. Christian wrote a bunch of such wrapper functions when we released Ultimate Toolbox 2005 - because the code has to compile on VC 6, VC 2003, and VC 2005.

 
Regards,
Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
Currently working on C++/CLI in Action for Manning Publications. (*Sample chapter available online*)

GeneralRe: Would be better to wrap it Unicode-compliantlyeditorNishant Sivakumar17 Nov '06 - 4:40 
Oh btw, nice article. Though it could have done with a screenshot Poke tongue | ;-P
 
Regards,
Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
Currently working on C++/CLI in Action for Manning Publications. (*Sample chapter available online*)

GeneralRe: Would be better to wrap it Unicode-compliantlymemberJohn Simmons / outlaw programmer17 Nov '06 - 5:02 
I was going to post a screen shot of my avatar, but I couldn't find one big enough to make an impression.

 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

GeneralRe: Would be better to wrap it Unicode-compliantlymemberJohn Simmons / outlaw programmer17 Nov '06 - 5:01 
Like I said, expanding on the idea is a minor exercise for most C++ programmers. Smile | :)
 
In our specific implementation, we're not using unicode so it honestly didn't occur to me.
 


 

"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 17 Nov 2006
Article Copyright 2006 by John Simmons / outlaw programmer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid