I'm continuing to work on my math parser. It was running fine on my home computer compiled with VisC++ 8.0. Since I have some free time at school, I decided to work on it there. The problem is I received alot of warnings
strcpy being deprecated use strcpy_s
sprintf "" sprintf_s
So I bit the bullet and started using std::string's. I'm not too familiar with them so I need some help. How would I go about doing this with strings:
char temp[ 256 ] = ""; sprintf( temp, "The value is %d", value );
I tried this and that didn't work.
std::string temp; temp = "The value is " + value;
It is a problem of MSVC. strcpy is a standard function and no other compiler depricates it besides MSVC. Ignore the warnings and keep on using strcpy if you need it.
For std::string see this, especially the append member function.
I think Microsoft was deprecating the versions without lenght to prevent bugs.
strcpy is being deprecated because say you have
char buffer[5];
strcpy(buffer, "Oh man I'm bigger than 4");
You'll start overwriting your code in memory. strcpy_s takes the size of the buffer and makes sure it's not overrun. It's a classical way hackers can take over a system - buffer overrun.
strcpy_s is a winapi specific function. strncpy would do exactly the same thing and would be cross-platform.
ReyBrujo is correct with this: with the infamous AOL/MSN buffer exploits that happened so many years ago, they're trying to get away from functions that don't prevent buffer overruns. strncpy() will read up to, but not more than, the given number. Otherwise, you could declare a string of length 100, and if the user writes 104 or 108 bytes, then it can corrupt the stack or be used as an exploit.
I guess it's better to deprecate it to force programmers to start learning how to program "safely"
HoHo
None of those deal with values in terms of int or long or ...
int value = 25; std:string str = ""; str = "The value is " + value;
gives me 'The value is ***GARBAGE ***'
The C++ way to format strings is to use std::stringstream:
#include <iostream> #include <sstream> #include <string> int main() { int value = 25; std::stringstream temp; temp << "The value is " << value; std::string s(temp.str()); std::cout << s << '\n'; }
The best I can do to explain, why your example compiles, is that the compiler might see this as pointer arithmetics: The first part, the string literal, is actually seen as a constant char* (which one can assign to the string). Then you add 25 to the pointer, getting another char pointer pointing 25 chars onward in the memory. Whatever happens to be there, up to the first 0 character, is copied to the string.
Hmm, so if you don't know what you are doing, std::string can be unsafe too...
To do that kind of things in C++ you use stringstream
I think Microsoft was deprecating the versions without lenght to prevent bugs.
No, those are derecated, too.
And, as clearly stated in the warning, simply define _CRT_SECURE_NO_DEPRECATE to disable the warnings.
You can turn off those warnings in VS and go with the standard instead of Microsofts usual way of working against portability and standards.
The C++ way to format strings is to use std::stringstream:
That, or boost::lexical_cast<> or boost::format<>.
Be careful with strncpy, in some situations it doesn't add terminating characters:
http://developer.apple.com/documentation/Darwin/Reference/Manpages/man3/strncpy.3.html
For anyone getting the deprecation warnings with msvc 8, just put this before any #includes:
#define _CRT_SECURE_NO_DEPRECATE
I appreciate BAF for reading my posts!
For std::string, besides the methods already suggested, you may use:
template<typename T> std::string to_string(const T &value) { std::ostringstream ret; ret << value; return ret.str(); }
---------------------------------
std::string temp; temp = "The value is " + to_string(value);
Wouldn't that be to_string<value_type>(value); ? Or do I not know how to use templates with functions (I've only ever used them with classes)?
BAF: No, that would not be to_string<value_type>(value);, as the template type can be automatically determined by the arguments of the function (now, if the return type was a template parameter that isn't mentioned in the argument list, you would need to specify it that way.)
Make your own:
1 | #include <stdio.h> |
2 | |
3 | char* strcopy(char* dest, char* src) |
4 | { |
5 | int i = 0; |
6 | |
7 | while(src<i>) |
8 | { |
9 | dest<i> = src<i>; |
10 | i++; |
11 | } |
12 | |
13 | dest<i> = 0; |
14 | |
15 | return dest; |
16 | } |
17 | |
18 | int main() |
19 | { |
20 | char dest[10]; |
21 | char src[] = "foobarbaz"; |
22 | |
23 | strcopy(dest, src); |
24 | printf("%s\n", dest); |
25 | |
26 | return 0; |
27 | } |
Be careful with strncpy, in some situations it doesn't add terminating characters:
Wasn't there supposed to be a new function to take care of that? strlcpy or something. I'm positive I read something about that once, and it also fixed the issue of strncpy filling the rest of the destination string with null chars (a potential performance problem). I don't have it in my man pages, though..
It's a OpenBSD (or *BSD) function. The glibc folks don't like it.
char* strcopy(char* dest, char* src) { int i = 0; while(src<i>) { dest<i> = src<i>; i++; } dest<i> = 0; return dest; }
Personally, I prefer this for strcpy
void strcopy(char* dest, char* src) { while( *dest++ = *src++ ); }
and this for strncpy
void strncopy(char* dest, char* src, size_t len) { size_t current = 0; while( *dest++ = *src++ && ++current < len ); *dest = 0; }
Untested, though.
and this for strncpy
...
Untested, though.
Hello, Mr. Buffer Overflow. Nice to meet you.
That writes one byte past the end of the dest buffer. Perhaps something like this:
void strncopy(char* dest, char* src, size_t len) { if(len) { size_t current = len-1; while( current-- ) *(dest++) = *(src++); *dest = 0; } }
KC: Yeah, I should have caught that. I did state untested though (I should have checked len's validity, then done *(dest-1) = 0 as dest is already past the end at that point...)
I think Microsoft was deprecating the versions without lenght to prevent bugs.
Maybe thats how the idea came up. But it ended up being more of a way to lock people into WINBLOWS specific code and make porting away from windows harder.
void strcopy(char* dest, char* src) { while( *dest++ = *src++ ); }
It's efficient, but isn't compatible with strcpy() since it doesn't return the original dest. That is all.
Also nobody seemed to get the parameters right, it ischar* dest, const char* src
const is for wimps.
... and for compiler that wants to optimize as much as possible
... and for compiler that wants to optimize as much as possible
For the "smarter" ones, it often makes no difference.;)
Maybe thats how the idea came up. But it ended up being more of a way to lock people into WINBLOWS specific code and make porting away from windows harder.
Actually, I would bet the amount of strn.* functions in the Linux kernel overwhelms the str[^n]+ ones. At least, that is what I would expect.
For the "smarter" ones, it often makes no difference.;)
You've found smart compilers? Where? Are they less then $10000 a license? *
* This is a joke. Compilers are very far from perfect.
char* dest, const char* src
Well, of course. Here, lets make it complete:
char* strcpy(char* dest, const char* src) { char* temp = dest; while( *dest++ = *src++ ); return temp; }
Or, better yet:
#include <algorithm> char* strncpy(char* dest, const char* src, const size_t len) { std::copy(src, src+len, dest); // hooray for the STL! *(dest+len-1) = 0; return dest; }
Congratulations! You've just added 2MB to the executable.
Congratulations! You've just added 2MB to the executable.
1 | #include <algorithm> |
2 | |
3 | char* strncpy(char* dest, const char* src, const size_t len) { |
4 | std::copy(src, src+len, dest); // hooray for the STL! |
5 | *(dest+len-1) = 0; |
6 | return dest; |
7 | } |
8 | |
9 | int main(){ |
10 | char *str1=new char[10], *str2=new char[10]; |
11 | strncpy(str2, str1, 9); |
12 | return 0; |
13 | } |
14 | |
15 | #g++ test.cpp |
16 | #ls -l a.out |
17 | -rwxr-xr-x 1 hoho users 7061 Mar 10 02:04 a.out |
If in doubt, benchmark
You've found smart compilers? Where? Are they less then $10000 a license? *
This is a joke. Compilers are very far from perfect.
Hence the quotes around and usage of "smarter" rather than "smart". I know all too well; my recent experiences with the way GCC reacts to and handles x87 (ye olde register-stack-based x86 FPU) inline assembly makes me feel like hand-coding all my DSP code in assembly.
-rwxrwxrwx+ 1 Administrators None 248 Mar 9 22:46 c_version.c* -rwxr-xr-x 1 ppridham None 7691 Mar 9 22:47 c_version.exe* -rwxrwxrwx+ 1 Administrators None 335 Mar 9 22:47 stl_version.cpp* -rwxr-xr-x 1 ppridham None 41201 Mar 9 22:47 stl_version.exe*
Huh. Pretty bloated in Cygwin it seems.
Try compiling with -O2 -ffast-math -fomit-frame-pointer
Better with -Os and maybe with -fomit-frame-pointer
Also a mingw und UPx compressing might be interesting.
Carrus85 version of strncpy (no optimizations, -Os):
-rwxr-xr-x 1 hoho users 6644 Mar 10 10:48 a.out -rwxr-xr-x 1 hoho users 6604 Mar 10 10:48 a.out
libc strncpy:
-rwxr-xr-x 1 hoho users 6525 Mar 10 10:50 a.out -rwxr-xr-x 1 hoho users 6517 Mar 10 10:50 a.out
I wondeor how it is possible that libc's strncpy creates smaller executable than the function Carrus gave
Seems to me as there isn't much difference between C and C++, not at least under Linux
Another silly discussion but...
string copy(src) copy.c_str();
When did A.cc become the Royal Benchmarking Society? Some of the threads have become kind of like Programmer Mythbusters . "Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!".
I like to think the community has just moved away from it-is-so-because-guru-says-it-is mysticism.
The community has grown wiser
I like to think the community has just moved away from it-is-so-because-guru-says-it-is mysticism.
Using the ++ operator makes your programs larger.
Using the ++ operator makes your programs larger.
How very wise. Another little known fact is that for statements also make your programs larger!
I like to think the community has just moved away from it-is-so-because-guru-says-it-is mysticism.
I'd like to think that people benchmark more and guess less
Jakub Wasilewski, thanks for my new sig
The posted strncpy() replacement also violates the semantics of strncpy, namely that the destination buffer is padded up to the length if the source is shorter. And it's invalid if called with length 0.
There's no reason to reinvent these functions except for better portability... because doing so creates problems like this that lurk, just waiting to be exploited in released code.