This really isn’t a FreeRTOS question, but new String(“abc”) creates a String object on the heap, which points to another heap object to store the string itself (unless it uses a small-string optimization), so your str variable isn’t a String object, but a pointer to a String object.
Note also, the name of that class would be std::string, not String, which might be something you made yourself (like I have).
Unless you class is playing games, the size of the String object will be a constant, and typically will contain a pointer to the actual string data (and possible a small buffer for a small string optimization, perhaps overlapping the pointer). As such, you rarely create such an object with “new”, but it might create the final buffer for a longer string with new.
That is why the complier expects all objects to be the same size, as that is a requirement of the language. Objects of a given type WILL be the same size, and if they need an additional variable size, they will need to point to a dynamic buffer, from the heap.
My own string class contains 3 values in the object, a pointer to the payload string, a length of the string itself, and a length of the buffer that the string has been allocated (so I can over allocate at times to allow changing and not need to keep recreating it).
Please understand that the sizeof operator (and it’s an operator, not a function) is evaluated at compile time, not at runtime.
In most cases, a C++ string object is a descriptor that has a fixed size and has information within the descriptor for where the data is stored and the length, no matter what size your initializer string is, the compiler (and therefore sizeof) will not know about that, it knows the size of the descriptor (or if it’s a pointer, the size of that pointer). The string class you are using should have a method or property that you can query to get the length of the string.
There is a difference in sizeof(String) which is constexpr and sizeof(String*) which should be size_t at runtime.
I do understand that this information is missing, and that the compiler has to be updated. My problem is, it isn’t my compiler. If it was, i could fix this within hours.
I stay at my proposal to provide a dynamic constructor.
Thank You for Your reply, hopefully You can follow me.
It’s been some years since my involvement with the C standards committee or writing C compilers for a living, and C++ may have added a semantic to sizeof that I’m not aware of, but that would be what is called a “breaking change”, since the definition, and usage, of the sizeof operator has been established since the K&R days, and C++ never changed it in the years that I kept up with the C++ standard. I may be 7 or so years out of date, but I don’t think that sizeof is capable of returning the size of a dynamic allocation for a variable sized object.
I can say for sure that GCC and LLVM both have their problems, but their understanding of sizeof is probably not one of them.
Sorry, my days of C compiler development are long behind me.
And I could not change sizeof even if I wanted to.
The String class ought to have a method or property where you can get the storage size of the string data itself, but I’m not in a position to check that out.
I don’t understand what you mean by something missing.
Unless your class somehow overloads the sizeof and * operators in such a way as to make it give you the size of the data storage that is dynamically allocated, or simply give you the ‘.length’ or ‘.size’ property when doing sizeof(String*), it’s always going to return the size of a pointer to String. That is the definition of sizeof.
Not missing from the compiler. If you’re using a C++ std:string template for String, then s = new String("whatever") will make 2 allocations; the first is for the String object, and an allocation for the storage to put a copy of the characters of the string literal “whatever”. When you change the value of s, the class may do a realloc() on that storage or simply do a new malloc() large enough to hold the new string, update the storage pointer in the String object, update its length, and call free() on the original storage.
That is how C++ works.
Don’t expect C++, a compiled language, to act like Lua or Python, where taking the size of a string or other object is a runtime operation, not compile time.
sizeof is an operator in C++ that works on types and defined objects (you can use sizeof on a fixed length array). There exist other mechanisms to get the length of the allocated storage if you’re using any of the string classes for C++ I’ve ever encountered. If you can give me an example of a compiler that gives you the runtime evaluation you insist is correct for sizeof(String*), I’ll be very surprised. There have been C interpreters that did let the programmer see the size of a malloc()ed chunk of memory, but that was a bug, not a feature, and was never part of the C standard.
Just how this actually relates to FreeRTOS, which does not produce or provide a compiler toolchain itself, I’m not sure. Being confidently wrong may feel good, but until you find the right way to do what you’re doing, you’re never going to solve your problem.
sizeof(String*) is constexpr and returns the size of a string-pointer.
I meant sizeof(this) or sizeof(str).
This is why i suggest the dynamic constructor
size_t String::?String(char const*);
If present, the compiler knows that String has variable size and prevents the creation of String-arrays. Creation on the stack is still possible, however.
Sorry, please don’t get me wrong!
I’m missing this feature when overriding operator new. The compiler should give me the arguments there. I also want to return a Handle and no void*.
Variable sized objects are different, You cannot have an array anymore and not static_cast. The compiler has to be aware of that.
It is wrong to expect that all objects of the same class have the same size, at least for the String-class. It is really a mistake of the compiler.
sizeof(*this) is the size of the object, which must be a constant, as objects have fixed size, based on the size of there type.
C++ doesn’t support as part of the language the use of the unspecified array as part of a class or struct.
String CAN’T have a “variable size” as such a thing doesn’t exist. The C++ language just doesn’t have “variable-sized object types”. That is something just not defined. Even in C, the type of the object is always fixed, but there is a syntax to define and access an array that will be manually created after the object.
To do what you seem to want to do, would require that the “String” class be actually made with a “factory function” that allocates “raw bytes” and then uses “placement new” to build the base String class in the space, followed by the payload data.
This method is fragile, as if you ever try to create an array of these or derive from them you will get into trouble. This method normally makes the constructors private (which prevents all of those operations) and you can ONLY make the String class with the factory function.