I'm still very new to C++, and I'm having issues with allocating heap memory.
This is what I have in my header file:
const int NUM_WORDS = 1253;
const int CHAR_SIZE = 256;
class CWords
{
public:
// constructor(s)
CWords();
// destructor
~CWords();
// public member functions
void ReadFile();
const char* GetRandomWord() const;
private:
char* m_words[NUM_WORDS]; // NUM_WORDS pointers to a char
int m_numWords; // Total words actually read from the file
};
I'm trying to allocate space in the implementation cpp file, but I can't (default constructor):
CWords::CWords()
{
m_numWords = 0;
m_words = new char[strlen(m_words) + 1]; // LINE 31
strcpy(m_words, "NULL"); // LINE 32
}
line 31 gives me:
cannot convert 'char**' to 'const char*' for argument '1' to 'size_t strlen(const char*)'
and line 32 gives me:
cannot convert 'char**' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
I don't know what these errors mean.
The answer assumes that there is no strict requirement to force using C style arrays and strings.
As mentioned in the comments, even if you did manage the get rid of the bugs, this is not the recomended way to go in C++.
std::vector is the go-to container if you need a dynamic size array. std::array is for a static size one.
Also it is better to use std::string than C style strings. Doing so will save you the trouble of manual memory management (and the bugs that come with it).
Below is a modification of the header of your class:
#include <vector>
#include <string>
class CWords
{
public:
// constructor(s)
CWords();
// destructor
~CWords();
// public member functions
bool ReadFile();
std::string const & GetRandomWord() const;
private:
std::vector<std::string> m_words;
};
I'll leave the implementation for you.
Notes:
ReadFile returns a bool in my version (not void). Reading from a file may fail, and so it is better to return false to indicate an error.
If you ever consider to inherit from class CWord, you'd better make the destructor virtual. See here: Should every class have a virtual destructor?.
if m_words should represent multiple strings
In this case m_words is a static array with pointers pointing to several strings.
Hence it makes sense to initialize those pointers with NULL in your constructor (e.g. using a for loop for NUM_WORDS entries).
Beside that initialize the member m_numWords with 0. Obviously this member should contain the info how many entries of m_words are already filled.
if m_words should represent 1 string
Use char m_words[NUM_WORDS]; in your header file
then you don't need to dynamically allocate memory in the constructor (the memory is then part of every instance's size).
Or simply use a char* m_words; in your header file
and dynamically allocate as much chars as you need at a later time. This way you can free your string and allocate it with a different size whenever needed.
However in this case it is strongly recommended to initialize m_words with a NULL pointer in constructor.
Please also have a look at the strlen() description. It can only count the characters, that are already contained in your string.
Use sizeof() to measure the bytesize of static arrays.
Related
Im trying to create an array with the string::size member but its complaining at the declaration of "char message[msgSize]" that the expression did not evalute to a constant.
However it alows me to declare "msgSize".
How can this be? Why am i allowed to make a constant but i'm not allowed to use it to something that needs a const.
If the answer is that: "the size of the string could change" then the same argument can be made for using sizeof(), but that works.
const unsigned int msgSize =
saveAs.size() +
sizeof("NOTE| sent get request to: ") + 10;
char message[msgSize];
memset(message, 0, msgSize);
sprintf_s(message, msgSize,"NOTE| sent get request to: %s", saveAs.c_str());
_cRec->output(message);
Well const just means that you promise that the value won't change. And you can even override that with a const_cast.
What compiler needs there is a value that can be evaluated at the compile time. This is a stronger requirement. Such values are marked with constexpr keyword.
Unfortunately you are out of luck with std::string... size() is not a constexpr.
I played with the following example:
#include <iostream>
#include <string>
using namespace std;
const string msg("Some msg");
constexpr int msg_len = msg.size();
int main() {
char msg[msg_len];
cout << sizeof(msg);
return 0;
}
The thing is that size() is not a constexpr, and you cannot make string a constexpr because it has a non-trivial destructor.
Why it is designed this way is beyond me. Seems like a counter intuitive and serious limitation. However, there are pretty clever implementation of string, for example with small storage optimization. It might be hard to make them constexpr with out serious changes in the implementation.
You would have to make your array dynamic.
The size of the string is not known at compile time, but only at run time.
Also, your listing is not a minimal compilable example. I can only assume saveAs is an std::string.
The following would work:
int main()
{
std::string myString("My string");
char * myCStyleString = new char[myString.size()];
delete[] myCStyleString;
}
because we are dynamically allocating an array there.
What are you trying to do? It looks like you just want to copy a filename into a message string. Just keep using std::string;
int main()
{
std::string myString("My string");
std::string message = "I like beans and rice with: ";
message += myString;
return 0;
}
but again, I'd need a minimal compilable example to determine your goal.
In C++ you cannot declare VLAs.
When you declare an array, for example:
char message[x];
The expression x must to be valuable at compile time, that is its value has to be well-known when the source is compiled.
In you example:
char message[msgSize];
The expression (variable) msgSize is not known at compile time, but only at run time. That because the compiler has to know how many bytes reserve in the stack.
Note: the variable msgSize is a constant value. A constant value is not an expression evaluate at compile time. It simply means that its value cannot change once has been assigned.
In C++11 has been introduced the keywork constexpr in order to define an expression which should be evaluate at compile time.
However in your case there is not way to get the size of a dynamic string at compile time. So what you have to do is use dynamic array (dynamic memory).
char* message = new char[msgSize];
// now you have an array of msgSize lenght
// ... do stuff...
// do not forget to release the memory when end
delete[] message;
Finally, I suggest you to re-elaborate your code because it's likely you don't need a dynamic array of chars, but just a std::string. Indeed you can use overloaded operator + in order to concatenate strings and the method std::string::c_str() to access as const char* for backward compatibility.
Why am i allowed to make a constant but i'm not allowed to use it to
something that needs a const.
This is because the "constant" expression you have is made up of non constant parts i.e. the size method of the string class. It is not truly constant in terms of having a known value at compile time.
Consider using constexpr variable/function in the future
If the answer is that: "the size of the string could change" then the
same argument can be made for using sizeof(), but that works.
No that same argument cannot be used for sizeof because sizeof does not need it's arguement to be a constant.
If you know for a fact that saveAs contains a string with a known size, then perhaps it would be best if you declare that size as a constant and then refer to it in your calculation:
constexpr unsigned int msgSize =
SAVEAS_SIZE +
sizeof("NOTE| sent get request to: ") + 10;
Then this will allow you to do:
char message[msgSize];
You need a compile-time constant with char message[msgSize]; because this is a local variable which uses static memory that is allocated in the data segment, so the compiler needs to calculate the number of bytes required by the code, including the local variables and arrays.
You can use dynamic memory to solve your problem. The dynamic memory is allocated in the heap. In C, you should use malloc(). In C++, you should use new[] (or better, std::vector, or even std::string). Then you can specify the memory size using a runtime value in a variable.
So, your code would look more like the follow:
char* message = new char[msgSize]; //Allocated memory
//Do everything that you need...
delete[] message; //Release memory
Or:
#include <vector>
std::vector<char> message(msgSize); //Allocated memory
//Do everything that you need...
Imagine that MyTextClass is a custom class that in this case would hold the passed const char "Hello stackoverflowers" into a std::vector<char>:
class MyTextClass{
private:
std::vector<char> storage;
public:
MyTextClass(const char* _passedchars) //constructor
}
With something like the code above, I want to initialize an instance of MyTextClass by passing a text to it:
MyTextClass textholder("Hello stackoverflowers");
Or even the following if I overload the = operator within MyTextClass:
MyTextClass textholder = "Hello stackoverflowers";
The problem becomes figuring out what the definition of the MyTextClass constructor should look like. I say that because while there is no problem in the constructor receiving a const char passed directly as text like "Hello stackoverflowers", that is an array an thus its length:
1) can't be devised in advance (because it's a passed text of unknown length);
2) nor figured out within the constructor (because sizeof(_passedchars)/sizeof(_passedchars[0]) will only assess the the size of the pointer;
3) and also not retrieved with std::size or the use of std::begin and std::end, since there is no implementation of those for const char.
And without such informations, I just can't figure it out how to convert the const char parameter _passedchars of the constructor of MyTextClass into the internal std::vector<char> that I called storage in the code example above.
Therefore, how could I convert the passed const char into a std:vector<char> within a function, in the case of wanting to create an own char text class?
You can use strlen to determine the length of a C-style string.
Alternatively, you could change the parameter type to std::string and use its size or length function to get the length of the string.
To use this exact constructor declaration you could write (in the class definition in the header):
MyTextClass(const char* _passedchars)
: storage( _passedchars, _passedchars + strlen(_passedchars) )
{
}
(note: requires #include <string.h> for strlen).
However the string literal is actually an array. By accepting a pointer you lost the length information which was already available. So you could instead have the constructor as:
template<size_t N>
MyTextClass( const char (&passed)[N] )
: storage( passed, passed + N - 1 )
{
}
In the latter case you could use std::begin(passed), std::end(passed) instead.
This question already has answers here:
C++ Error: Incompatible types in assignment of ‘char*’ to ‘char [2]
(3 answers)
Closed 9 years ago.
So I trying to build this program that will take two char and a double. Once the user has input the information. I will transfer the information to an object by using the function below.
But every time I try to compile i get this error incompatible types in assignment of const char* to char [20]. Can anyone give me a hand and clarify when im not understanding. Thanks in advance.
void Molecule::set(const char* sym, const char* type, double weighT);
And this how I call it.
molecule[i].set(symbol, description,weight);
And within the set() function I just have to transfer the values inpputed to my private member in my object which i did by using this-> function.
////So This part is supposed to transfer the value to my Class Molecule private members////
this->symbol_ = sym;
this->type_ = type;
this->weight_ = weighT;
///////Here is my Class Molecule////////
class Molecule{
private:
char symbol_[20];
char type_[20];
double weight_;
public:
void set(const char* sym, const char* type, double weighT);
void display() const;
};
You need to use strcpy or similar to copy the strings from your char * to your class's char []. Using = is attempting to copy the pointer but they are indeed incompatible types.
This code
this->symbol_ = sym;
this->type_ = type;
is invalid. Arrays have no the copy assignment operator. You should use either standard C function strcpy or strncpy that are declared in header <cstring>
For example
std::strncpy( this->symbol, sym, 20 );
this->symbol[19] = '\0';
std::strncpy( this->type, type, 20 );
this->type[19] = '\0';
Also it is a good idea to assign a name for magic number 20 either using an enumerator or static constant.
Also instead of character arrays you could use standard class std::string that has several overloaded assignment operators.
symbol_ is a char[], you need to use stcpy to fill it.
In set method :
this->symbol_ = sym;
should becomes
stncpy(this->symbol_, sym, 20);
Or simpler define symbol_ as an std::string replacing :
char symbol_[20];
with
std::string symbol_;
Pointers and Arrays are not the same thing, although it is easy to believe that they are.
Arrays can be passed as arguments to functions that request pointers because of pointer decay, and that can lead people to believe that they are interchangeable.
See this article: What is array decaying?
When you declare symbol_[20], this tells the class to allocate 20 bytes when the object is created. symbol_ will always point to this allocation. You cannot reassign it as you could with a pointer.
You probably will want to copy the text pointed to by sym using std::strncpy. Be careful, though. If the string pointed to by sym is bigger than 19 characters (19 + 1 for the null character at the end), then you will need to terminate your symbol_ array with a null character (\0) manually for it to be a valid string.
#include <cstring>
...
std::strncpy(symbol_, sym, sizeof(symbol));
symbol_[19] = '\0';
I didn't get the chance to compile the code above, so, it might be best to study the example at the end of this article:
http://www.cplusplus.com/reference/cstring/strncpy/?kw=strncpy
struct testing
{
char lastname[20];
};
testing *pt = new testing;
pt->lastname = "McLove";
and I got
56 C:\Users\Daniel\Documents\Untitled2.cpp incompatible types in
assignment of 'const char[7]' to 'char[20]'
Why ?
Thanks in advance.
Because compile time arrays are constant. In your struct testing, you have an array of 20 chars, and you're trying to assign a pointer ("McLove", a compile time string, e.g., a const char*) to an array (a char[]), which won't work.
To copy the data "McLove" into the array, you need to use strncpy:
strncpy(pt->lastname, "McLove", 20); // 20 is the size of the array, change it when your array size changes, or better yet, use a constant for both
Or better yet, use std::string:
struct testing {
string lastname;
};
testing* pt = new testing;
pt->lastname = "McLove";
And now that will work, because std::string has an operator= that works with const char*.
As a side note, don't needlessly allocate objects on the free store (using new); allocate them on the stack:
testing pt; // not: testing* pt = new testing;
testing.lastname = "McLove"; // with std::string
The type of a string literal is pointer to const char. You can use that to initialize an array of char, but you can't assign to an array of char (from that or anything else).
Since you're apparently doing C++, you probably want:
struct testing {
std::string lastname;
};
testing pt;
pt.lastname = "McLove";
Allocating an object like testing dynamically is fairly unusual.
You can't assign one array to another. You're going to need to use strcpy (or better, strncpy).
Because string literals in C++ have the type const char[N] where N is the length of the literal, including the NULL character. So you're trying to assign a const char[7] to a array of type char[20], exactly what the compiler told you. Since arrays are not assignable this is invalid.
Use strcpy instead
strcpy( p-lastname, "McLove" );
Of course, you should also check if the destination is large enough to hold the source, or use some variant of strcpy that does this.
Was reading up a bit on my C++, and found this article about RTTI (Runtime Type Identification):
http://msdn.microsoft.com/en-us/library/70ky2y6k(VS.80).aspx . Well, that's another subject :) - However, I stumbled upon a weird saying in the type_info-class, namely about the ::name-method. It says: "The type_info::name member function returns a const char* to a null-terminated string representing the human-readable name of the type. The memory pointed to is cached and should never be directly deallocated."
How can you implement something like this yourself!? I've been struggling quite a bit with this exact problem often before, as I don't want to make a new char-array for the caller to delete, so I've stuck to std::string thus far.
So, for the sake of simplicity, let's say I want to make a method that returns "Hello World!", let's call it
const char *getHelloString() const;
Personally, I would make it somehow like this (Pseudo):
const char *getHelloString() const
{
char *returnVal = new char[13];
strcpy("HelloWorld!", returnVal);
return returnVal
}
.. But this would mean that the caller should do a delete[] on my return pointer :(
Thx in advance
How about this:
const char *getHelloString() const
{
return "HelloWorld!";
}
Returning a literal directly means the space for the string is allocated in static storage by the compiler and will be available throughout the duration of the program.
I like all the answers about how the string could be statically allocated, but that's not necessarily true for all implementations, particularly the one whose documentation the original poster linked to. In this case, it appears that the decorated type name is stored statically in order to save space, and the undecorated type name is computed on demand and cached in a linked list.
If you're curious about how the Visual C++ type_info::name() implementation allocates and caches its memory, it's not hard to find out. First, create a tiny test program:
#include <cstdio>
#include <typeinfo>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int> v;
const type_info& ti = typeid(v);
const char* n = ti.name();
printf("%s\n", n);
return 0;
}
Build it and run it under a debugger (I used WinDbg) and look at the pointer returned by type_info::name(). Does it point to a global structure? If so, WinDbg's ln command will tell the name of the closest symbol:
0:000> ?? n
char * 0x00000000`00857290
"class std::vector<int,class std::allocator<int> >"
0:000> ln 0x00000000`00857290
0:000>
ln didn't print anything, which indicates that the string wasn't in the range of addresses owned by any specific module. It would be in that range if it was in the data or read-only data segment. Let's see if it was allocated on the heap, by searching all heaps for the address returned by type_info::name():
0:000> !heap -x 0x00000000`00857290
Entry User Heap Segment Size PrevSize Unused Flags
-------------------------------------------------------------------------------------------------------------
0000000000857280 0000000000857290 0000000000850000 0000000000850000 70 40 3e busy extra fill
Yes, it was allocated on the heap. Putting a breakpoint at the start of malloc() and restarting the program confirms it.
Looking at the declaration in <typeinfo> gives a clue about where the heap pointers are getting cached:
struct __type_info_node {
void *memPtr;
__type_info_node* next;
};
extern __type_info_node __type_info_root_node;
...
_CRTIMP_PURE const char* __CLR_OR_THIS_CALL name(__type_info_node* __ptype_info_node = &__type_info_root_node) const;
If you find the address of __type_info_root_node and walk down the list in the debugger, you quickly find a node containing the same address that was returned by type_info::name(). The list seems to be related to the caching scheme.
The MSDN page linked in the original question seems to fill in the blanks: the name is stored in its decorated form to save space, and this form is accessible via type_info::raw_name(). When you call type_info::name() for the first time on a given type, it undecorates the name, stores it in a heap-allocated buffer, caches the buffer pointer, and returns it.
The linked list may also be used to deallocate the cached strings during program exit (however, I didn't verify whether that is the case). This would ensure that they don't show up as memory leaks when you run a memory debugging tool.
Well gee, if we are talking about just a function, that you always want to return the same value. it's quite simple.
const char * foo()
{
static char[] return_val= "HelloWorld!";
return return_val;
}
The tricky bit is when you start doing things where you are caching the result, and then you have to consider Threading,or when your cache gets invalidated, and trying to store thing in thread local storage. But if it's just a one off output that is immediate copied, this should do the trick.
Alternately if you don't have a fixed size you have to do something where you have to either use a static buffer of arbitrary size.. in which you might eventually have something too large, or turn to a managed class say std::string.
const char * foo()
{
static std::string output;
DoCalculation(output);
return output.c_str();
}
also the function signature
const char *getHelloString() const;
is only applicable for member functions.
At which point you don't need to deal with static function local variables and could just use a member variable.
I think that since they know that there are a finite number of these, they just keep them around forever. It might be appropriate for you to do that in some instances, but as a general rule, std::string is going to be better.
They can also look up new calls to see if they made that string already and return the same pointer. Again, depending on what you are doing, this may be useful for you too.
Be careful when implementing a function that allocates a chunk of memory and then expects the caller to deallocate it, as you do in the OP:
const char *getHelloString() const
{
char *returnVal = new char[13];
strcpy("HelloWorld!", returnVal);
return returnVal
}
By doing this you are transferring ownership of the memory to the caller. If you call this code from some other function:
int main()
{
char * str = getHelloString();
delete str;
return 0;
}
...the semantics of transferring ownership of the memory is not clear, creating a situation where bugs and memory leaks are more likely.
Also, at least under Windows, if the two functions are in 2 different modules you could potentially corrupt the heap. In particular, if main() is in hello.exe, compiled in VC9, and getHelloString() is in utility.dll, compiled in VC6, you'll corrupt the heap when you delete the memory. This is because VC6 and VC9 both use their own heap, and they aren't the same heap, so you are allocating from one heap and deallocating from another.
Why does the return type need to be const? Don't think of the method as a get method, think of it as a create method. I've seen plenty of API that requires you to delete something a creation operator/method returns. Just make sure you note that in the documentation.
/* create a hello string
* must be deleted after use
*/
char *createHelloString() const
{
char *returnVal = new char[13];
strcpy("HelloWorld!", returnVal);
return returnVal
}
What I've often done when I need this sort of functionality is to have a char * pointer in the class - initialized to null - and allocate when required.
viz:
class CacheNameString
{
private:
char *name;
public:
CacheNameString():name(NULL) { }
const char *make_name(const char *v)
{
if (name != NULL)
free(name);
name = strdup(v);
return name;
}
};
Something like this would do:
const char *myfunction() {
static char *str = NULL; /* this only happens once */
delete [] str; /* delete previous cached version */
str = new char[strlen("whatever") + 1]; /* allocate space for the string and it's NUL terminator */
strcpy(str, "whatever");
return str;
}
EDIT: Something that occurred to me is that a good replacement for this could be returning a boost::shared_pointer instead. That way the caller can hold onto it as long as they want and they don't have to worry about explicitly deleting it. A fair compromise IMO.
The advice given that warns about the lifetime of the returned string is sound advise. You should always be careful about recognising your responsibilities when it comes to managing the lifetime of returned pointers. The practise is quite safe, however, provided the variable pointed to will outlast the call to the function that returned it. Consider, for instance, the pointer to const char returned by c_str() as a method of class std::string. This is returning a pointer to the memory managed by the string object which is guaranteed to be valid as long as the string object is not deleted or made to reallocate its internal memory.
In the case of the std::type_info class, it is a part of the C++ standard as its namespace implies. The memory returned from name() is actually pointed to static memory created by the compiler and linker when the class was compiled and is a part of the run time type identification (RTTI) system. Because it refers to a symbol in code space, you should not attempt to delete it.
I think something like this can only be implemented "cleanly" using objects and the RAII idiom.
When the objects destructor is called (obj goes out of scope), we can safely assume that the const char* pointers arent be used anymore.
example code:
class ICanReturnConstChars
{
std::stack<char*> cached_strings
public:
const char* yeahGiveItToMe(){
char* newmem = new char[something];
//write something to newmem
cached_strings.push_back(newmem);
return newmem;
}
~ICanReturnConstChars(){
while(!cached_strings.empty()){
delete [] cached_strings.back()
cached_strings.pop_back()
}
}
};
The only other possibility i know of is to pass a smart_ptr ..
It's probably done using a static buffer:
const char* GetHelloString()
{
static char buffer[256] = { 0 };
strcpy( buffer, "Hello World!" );
return buffer;
}
This buffer is like a global variable that is accessible only from this function.
You can't rely on GC; this is C++. That means you must keep the memory available until the program terminates. You simply don't know when it becomes safe to delete[] it. So, if you want to construct and return a const char*, simple new[] it and return it. Accept the unavoidable leak.