I'm trying to build a function that compacts the sprintf function, but somehow I ran into the following problem:
The first line after calling the class (It used to be a function, but that didn't work either) I get the correct result: http://puu.sh/1m1Bw
But the line after I get something completely different, while I didn't even touch the class or the variable: http://puu.sh/1m1BR
Can someone explain to me what's happening here?
Edit: Forgot the actual class:
StringCreator::StringCreator(char* _parten, ...) {
char buff[255];
va_list args;
va_start (args, _parten);
vsprintf (buff,_parten, args);
va_end(args);
this->str = buff;
}
And in the .h file:
class StringCreator {
public:
StringCreator(char* _parten, ...);
char* str;
};
After the StringCreator() constructor is complete the member variable this->str is a dangling pointer as it is pointing to buff which is a local variable of the constructor. Accessing this->str after the constructor is undefined behaviour. Changing str from a char* to a std::string is a solution and if you need access to a const char* you can use str.c_str(). Using a std::string also means the default copy constructor and assignment operator are correct.
If, as indicated in the comment to this answer, you new char[255] instead of using a std::string, then you need to either make StringCreator non-copyable or implement a copy constructor and assignment operator that copies the content of str. See What is The Rule of Three? Alternatively, you could have char str[255]; and avoid dynamic allocation and default copying of StringCreator would be correct.
To avoid potential buffer overrun on the call to vsprintf() use vsnprintf() instead (if your compiler supports C99) which accepts as an argument the size of the buffer being populated and does not write more than the specified size.
Related
Say I have a variable
std::string str; // initialized with some value
And a struct defined as:
struct test
{
public:
const char* name;
};
I know this can be done :
test t1;
t1.name = str.c_str();
But this will store the address of the variable str in t1.name
Instead I want the values of str to put in a char array member of the structure which should be of exact same size as variable str.
Is there a way that can be achieved or a better design
Thanks in advance!
But this will store the address of the variable str in t1.name
Not exactly. str.c_str() does not return the address of variable str. It returns the address of the character array owned by str.
Instead I want the values of str to put in a char array member of the structure
To do that, the structure must have a char array member. Your structure does not; it has a pointer member.
char array member of the structure which should be of exact same size as variable str.
This is not possible. The size of the string is dynamic i.e. it may change at run time. The size of a member array must be known at compile time.
You can instead allocate an array dynamically. As the name implies, the size of dynamic allocation may be determined at run time. However, dynamic allocations must be manually deallocated, or else your program will leak memory.
or a better design
A popular design pattern for dynamic allocation is RAII. The standard library already has a RAII container for character strings: std::string. So, to copy a string into a member of a struct, a good design is to have a string as the member:
struct test {
std::string name;
};
test t1;
t1.name = str;
There is no reason to use const char *, since its more error-prone and harder to implement you should use std::string instead.
std::string also allows you to get const char * to string using c_str() method.
But if you have to implement name as C-style string, here is what you have to do:
Allocate enough space on heap using new.
Cast to non-const
Copy strings using strcpy
Free memory in destructor
Constructor:
test(const std::string& str) : name(new char[str.length() + 1])
{
strcpy((char*)name, str.c_str()); }
};
[Live demo]
Also as #Pixelchemist correctly noted, there are important rules of zero/three/five. If your class contains resources which arent copied/destructed correctly them self, like pure pointers aren't (if you would use smart pointers, it would be different story), you have to implement these as well:
copy constructor
copy assignment operator
destructor
move constuctor
move assignment operator
For extended informations read this excellent answer about rule of three.
I have a function f returning a char*. The function documentation says:
The user must delete returned string
I want to construct a std::string from it. The trivial things to do is:
char* cstring = f();
std::string s(cstring);
delete cstring;
Is it possibile to do it better using C++ features? I would like to write something like
std::string(cstring)
avoiding the leak.
std::string will make a copy of the null terminated string argument and manage that copy. There's no way to have it take ownership of a string you pass to it. So what you're doing is correct, the only improvement I'd suggest is a check for nullptr, assuming that is a valid return value for f(). This is necessary because the std::string constructor taking a char const * requires that the argument point to a valid array, and not be nullptr.
char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring; // You most likely want delete[] and not delete
Now, if you don't need all of std::string's interface, or if avoiding the copy is important, then you can use a unique_ptr to manage the string instead.
std::unique_ptr<char[]> s{f()}; // will call delete[] automatically
You can get access to the managed char * via s.get() and the string will be deleted when s goes out of scope.
Even if you go with the first option, I'd suggest storing the return value of f() in a unique_ptr before passing it to the std::string constructor. That way if the construction throws, the returned string will still be deleted.
There is no standard way for a std::string to take ownership of a buffer you pass.
Nor to take responsibility of cleaning up such a buffer.
In theory, an implementation, knowing all the internal details, could add a way for a std::string to take over buffers allocated with their allocator, but I don't know of any implementation which does.
Nor is there any guarantee doing so would actually be advantageous, depending on implementation-details.
This code can never be correct:
std::string s(cstring);
delete cstring;
The std::string constructor that takes a character pointer, requires a NUL-terminated string. So it is multiple characters.
delete cstring is scalar delete.
Either you are trying to create a string from a character scalar (in which case, why the indirection?)
std::string s(cstring[0]);
delete cstring;
or you have multiple characters, and should delete accordingly
std::string s(cstring);
delete [] cstring;
Check the other answers for the recommended way to make sure delete[] gets used, e.g.
std::string(std::unique_ptr<char[]>(f()).get())
std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
std::string s = buff?buff.get():""; // handle null pointers
return s;
}
std::string steal_char_buffer( const char* str ) {
std::unique_ptr<char[]> buff(str); // manage lifetime
return steal_char_buffer(std::move(buff));
}
now you can type
std::string s = steal_char_buffer(f());
and you get a std::string out of f().
You may want to make the argument of steal_char_buffer be a const char*&&. It is mostly pointless, but it might lead to some useful errors.
If you can change the interface of f, make it return a std::string directly or a std::unique_ptr<char[]>.
Another good idea is to wrap f in another function that returns a std::unique_ptr<char[]> or std::string:
std::unique_ptr<char[]> good_f() {
return std::unique_ptr<char[]>(f());
}
and/or
std::string good_f2() {
auto s = good_f();
return steal_char_buffer( std::move(s) );
}
I have a function f returning a char*. The function documentation says:
The user must delete returned string
I want to construct a std::string from it. The trivial things to do is:
char* cstring = f();
std::string s(cstring);
delete cstring;
Is it possibile to do it better using C++ features? I would like to write something like
std::string(cstring)
avoiding the leak.
std::string will make a copy of the null terminated string argument and manage that copy. There's no way to have it take ownership of a string you pass to it. So what you're doing is correct, the only improvement I'd suggest is a check for nullptr, assuming that is a valid return value for f(). This is necessary because the std::string constructor taking a char const * requires that the argument point to a valid array, and not be nullptr.
char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring; // You most likely want delete[] and not delete
Now, if you don't need all of std::string's interface, or if avoiding the copy is important, then you can use a unique_ptr to manage the string instead.
std::unique_ptr<char[]> s{f()}; // will call delete[] automatically
You can get access to the managed char * via s.get() and the string will be deleted when s goes out of scope.
Even if you go with the first option, I'd suggest storing the return value of f() in a unique_ptr before passing it to the std::string constructor. That way if the construction throws, the returned string will still be deleted.
There is no standard way for a std::string to take ownership of a buffer you pass.
Nor to take responsibility of cleaning up such a buffer.
In theory, an implementation, knowing all the internal details, could add a way for a std::string to take over buffers allocated with their allocator, but I don't know of any implementation which does.
Nor is there any guarantee doing so would actually be advantageous, depending on implementation-details.
This code can never be correct:
std::string s(cstring);
delete cstring;
The std::string constructor that takes a character pointer, requires a NUL-terminated string. So it is multiple characters.
delete cstring is scalar delete.
Either you are trying to create a string from a character scalar (in which case, why the indirection?)
std::string s(cstring[0]);
delete cstring;
or you have multiple characters, and should delete accordingly
std::string s(cstring);
delete [] cstring;
Check the other answers for the recommended way to make sure delete[] gets used, e.g.
std::string(std::unique_ptr<char[]>(f()).get())
std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
std::string s = buff?buff.get():""; // handle null pointers
return s;
}
std::string steal_char_buffer( const char* str ) {
std::unique_ptr<char[]> buff(str); // manage lifetime
return steal_char_buffer(std::move(buff));
}
now you can type
std::string s = steal_char_buffer(f());
and you get a std::string out of f().
You may want to make the argument of steal_char_buffer be a const char*&&. It is mostly pointless, but it might lead to some useful errors.
If you can change the interface of f, make it return a std::string directly or a std::unique_ptr<char[]>.
Another good idea is to wrap f in another function that returns a std::unique_ptr<char[]> or std::string:
std::unique_ptr<char[]> good_f() {
return std::unique_ptr<char[]>(f());
}
and/or
std::string good_f2() {
auto s = good_f();
return steal_char_buffer( std::move(s) );
}
Is there any way to know if an object is a const object or regular object, for instance consider the following class
class String
{
String(const char* str);
};
if user create a const object from String then there is no reason to copy the passed native string and that because he will not make any manipulation on it, the only thing he will do is get string size, string search and other functions that will not change the string.
There is a very good reason for copying - you can't know that the lifetime of the const char * is the same as that of the String object. And no, there is no way of knowing that you are constructing a const object.
Unfortunately, C++ does not provide a way to do what you are attempting. Simply passing a const char * does not guarantee the lifetime of the memory being pointed to. Consider:
char * a = new char[10];
char const *b = a;
String c (b);
delete[] a;
// c is now broken
There is no way for you to know. You could write a class that tightly interacts with String and that creates a constant string pointing to an external buffer (by making the corresponding constructor private and making the interacting class a nested class or a friend of String).
If all you worry about is doing dynamic memory management on a potentially small constant string, you can implement the Small String Optimization (also Small Object/Buffer Optimization). It works by having an embedded buffer in your string class, and copying each string up to some predefined size into that buffer, and each string that's larger to a dynamically allocated storage (the same technique is used by boost::function for storing small sized function objects).
class String {
union {
char *dynamicptr;
char buffer[16];
};
bool isDynamic;
};
There are clever techniques for storing even the length of the embedded string into the buffer itself (storing its length as buffer[15] and similar trickeries).
You could use const_string to do what you're looking for. However, even with const string you have to "tell" it that the string doesn't need to be copied.
const char* foo = "c-string";
boost::const_string bar(foo); // will copy foo
boost::const_string baz(boost::ref(foo)); // assumes foo will always be a valid pointer.
if user create a const object from String then there is no reason to copy the passed native string and that because he will not make any manipulation on it, the only thing he will do is get string size, string search and other functions that will not change the string.
Oh yes there is. Just that it is passes as const doesn't mean that it actually is const outside of the constructor call, and it especially doesn't mean it won't be destroyed while the string object still exists. The keyword const for a function argument only means that the function won't modify or delete it (trying to implement a function that modifies a const argument will result in a compiler error), but there's no way for the function to know what happens outside.
What you're looking for is basically a COW (copy on write) string. Such things are entirely possible, but getting them to work well is somewhat non-trivial. In a multithreaded environment, getting good performance can go beyond non-trivial into the decidedly difficult range.
If I declare a function like this:
string hash (char* key)
then any change I make to key will also change it's value when the function exits, correct?
I want to make a copy of it in the function so that I can safely change it without changing the original value.
I tried this, but it doesn't work.
char temp = key;
How can it be done?
Probably the most obvious would be to change your parameter to a string:
std::string hash(std::string key) {
// ...
}
In a typical case, you'd want this to be a std::string const &, but in this case you want a modifiable copy of the original, so you pass the string by value. Since a string can be (implicitly) constructed from a char *, you can still pass pointers to char to it without a problem (and the compiler will construct a string automatically where needed).
std::string tmp(key);
tmp will be initialized to a copy of key. Make sure that key is null-terminated otherwise this will end in tears. See this for a overview of std::string ctors.
Declare the function as std::string hash(const char* key); this will make it obvious that key will not change and protects you from changing it by accident.
just use
string hash(char key)
this will push the char onto the stack and just its local version will be used within the scope of the function.
Oh, reading it again maybe you want to copy a string instead that a single char, in this case you can use strdup but don't forget to relese its memory at the end of the function. Finally you can also use the copy constructor of string class if you are planning to convert it to a std::string anyway..
I think your syntax for copying a char array into std::string is a bit wrong. To make a copy of a string just do this:
std::string copy(key);
On seconds thought, std::string = (char*)something should have worked, as string defines an assignment operator.
Use strcpy if you want to keep the parameter as a char pointer.
The definition:
char *strcpy(char *destination, const char *source);
You also use strdup
char temp = *key; I believe.