Why my char* is changing without reason? - c++

Details:
Im using this github project to convert a Json to an object.
https://github.com/ereilin/qt-json
With this json:
{
"bin": "/home/pablo/milaoserver/compile/Devices01.olk",
"temp":"/home/pablo/milaoserver/temporal/",
"port": "1234",
"name": "lekta",
}
with this two lines I create two char pointers:
char* bin = configuration["bin"].toString().toLatin1().data();
char* temp = configuration["temp"].toString().toLatin1().data();
Debugging the app I have the proper strings.
However when I use them, concretely the "bin" char changes to
`hom
Any Idea?
SOLUTION IN COMMENTS:
The problem was the "persistence" of the data.
I found the solution with:
std::string binAux(configuration["bin"].toString().toLatin1().data());
std::string tempAux(configuration["temp"].toString().toLatin1().data());
char* bin = new char[binAux.size()+1] ;
strcpy(bin, binAux.c_str());
char* temp = new char[tempAux.size()+1] ;
strcpy(temp, tempAux.c_str());

Your error here is because of temporary object.
toString() create a temporary object no longer available after the semicolon.
The standard state :
12.2 Temporary objects [class.temporary]
3/ [...] Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.
That is, when you want to access it you have Undefined Behavior.
This should solve your problem :
QString str = configuration["bin"].toString().toLatin1();
QByteArray ba = str1.toLatin1();
char *bin = ba.data();
But what do you want to use char* ? You are in C++, use std::string or Qstring instead :
#include <string>
std::string bin(configuration["bin"].toString().toLatin1().data());

Can you please try something like
std::string sbin(configuration["bin"].toString().toLatin1().data());
std::string sTemp(configuration["temp"].toString().toLatin1().data());

toString() creates a QString object that is deleted immediately, so the data that is contained in it will be freed. I do recommend you to store the data in a QString until you use that char* bin.

Your solution could be shorter, like this:
char* bin = strdup(configuration["bin"].toString().toLatin1().data().c_str());
char* temp = strdup(configuration["temp"].toString().toLatin1().data().c_str());
strdup() does virtually all you do.

Related

Temporary instance in C++ with strings and c-strings

So I have this code:
void blocks(std::string URL, std::string auth)
{
const char* cstr_url = URL.c_str();
std::string s = ("Authorization: " + auth);
const char* auth_header = s.c_str();
(··· and so on ···)
}
And everything seems fine if we look in the "autos" field in Debug mode:
But if we try to change the code in a way that ("Authorization: " + auth) is a temporary instance of the String class, in order to avoid declaring the s variable (and therefore saving space -at least, that's my purpose-):
void blocks(std::string URL, std::string auth)
{
const char* cstr_url = URL.c_str();
const char* auth_header = ("Authorization: " + auth).c_str();
(··· and so on ···)
}
...what we get in the Debug "autos" field is something quite different (lots of Ý chars):
I thought C++ could support these kind of things (which I don't know how are they technically called, I assume "implicit instance" as an original name). I would swear Java could support these "implicit instances" though.
So the actual question is, what's happening in here? Is there any workaround to avoid declaring an s variable?
The debug build has very kindly thoroughly destroyed the chars that ceased to exist after that statement, rather than leaving them in a state where you might think things were ok.
The C++ name for such things is "rvalue" (and specifically "prvalue"), which denotes the value category of the expression ("Authorization: " + auth). Rvalues are objects that are about to be destroyed.
auth_header is now an invalid pointer, and doing anything with it (besides re-assigning it) has undefined behaviour.

Passing char* to QString

I am working on a module in which GUI and back-end interact by message passing.
I initialised a char* as nullptr. GUI takes a QStringList which is tokenized. I cannot do the changes in the tokenized list. I receive a "(null)" in the list. Now I feel like by comparing to "(null)" is not the way to go. Is there any initialisation for char* which would be taken as an empty string by QString?
Use an empty string when constructing a QString when the pointer is NULL.
QString obj = (ptr == nullptr? QString("") : QString(ptr));
And then use obj.
Not sure to understand what you want but if i am not mistaken :
char *c = nullptr;
QString str(c);
str.isEmpty(); // return true

Pull the strings from a managed Listbox to a class variable of type char*

This is confusing. I understand pointers but what is with tracking references?
The instructions are not very clear on what to do even on the wiki, not to mention I was never taught this in adv C++. So, How do I get the items in a listbox into one of my classes?
Also is can i get a brief rundown of tracking references for future reference?
My form has a Listbox called listbox2 with some data in it.
My class called "ManifistOBJ" has a method called "setFilename(char*)"
Now in other programs i can easily add objects to the "AddFilename" method but how do i do it for a tracking reference?
Sofar iv tried:
DMManifest newmanifest = DMManifest();
for(int i =1;i< listBox2->Items->Count;i++)
{
ManifistOBJ newobj = ManifistOBJ();
System::String^ temp = listBox2->Items[i]->ToString();
String temp1 = temp;//?
char* temp2 = temp1.c_str();
newobj.setFilename(temp2);
newmanifest.push_back(newobj);
}
With that ^ next to string I cant DE-reference it. and I have no idea how to.
I could make the method take a string^ but that would mess up my other programs that use that library.
#include <msclr/marshal_cppstd.h>
System::String^ temp = listBox2->Items[i]->ToString();
std::string temp1 = msclr::interop::marshal_as< std::string >( temp );
C++/CLI Converting from System::String^ to std::string

QT Cannot convert 'std::string' to 'std::string*' in initialization

I got some problems in creating my program for mobile using QT C++
When i run it i get this: cannot convert 'std::string' to 'std::string*' in initialization
And theres code for that error:
void rozvrh_b17::pars(string par)
{
data = new std::string*(par);
printf(data->data());
}
//data and par are std::string
//without that new std::string*() it does similiar error
And i ask how to convert std::string to std::string* ??
EDIT:
i made this function to transfer data from one form to another and i need to remember that parameter...
I downvoted you because this question shows no research effort.
string * data = &par;
std::string* is a pointer type. You have a std::string, and it's address is the pointer type you want. This is one of the first principles of using pointers.
What do you really try to do?
If you just want to print the string then this should work:
void rozvrh_b17::pars(string par)
{
printf(par.c_str());
}
If you want to create a copy of string on the heap then you need this:
std::string* data = new std::string(par);
but that doesn't make much sense.
You are trying to assign a string from a pointer to string. In this particular case I see several things.
You don't need a copy at all - simply use par right away
You better make par a const ref: void rozvrh_b17::pars(const string& par)
You should use only string whaen calling new otherwise you create a pointer to string. So do: data = new std::string(par);

Is something wrong with wrapper classes for C string functions?

I have some C++ code written in C-style.
For some reasons I can't use C++ string and IO libraries, so for strings handling I should use only functions like sprintf, itoa, etc.
I want to replace C-style which requires temporary buffers
char buf[12];
itoa(x, buf, 16);
set_some_text(buf);
by the following code
class i2a
{
public:
explicit i2a(int value) { ::sprintf(buf, "%d", value); }
operator const char* () const { return buf; }
private:
char buf[12];
};
// usage:
set_some_text(i2a(x));
(Such classes can be written for char<->wchar_t convertions, etc.)
I see some cases when such classes will be dangerous:
For example, one can write
const char* someMeaningfulName = i2a(x);
// the right code should be i2a someMeaningfulName(x); or i2a someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);
In more complex case, a function which accepts text will not copy it, but will save pointer to it somewhere. For example it may be
class Foo { .... const char* p; };
Foo f(const char* text) { ... foo.p = text; return foo; }
it can be really unobvious, unlike const char* variable.
Is there a way to make such classes more secure?
Upd: why not std::string, boost::lexical_cast, boost::format, etc :
The code should work when compiled with -fno-except (C++ exceptions disabled - no throw, no stack unwinding). Also it should keep working on low memory conditions.
std::string, streams uses heap-allocated memory and at least throws bad_alloc.
When we have no free heap memory, usually we still have some kilobytes of stack (for example to write to user that we are out of memory and then make proper cleanup).
ATL and MFC String Conversion Macros are also written in this way. Calling the constructor directly like i2a(x) will create a temporary object that will live until the function to which it is passed is complete. So here: do_some(i2a(x)), the temporary object will be there until do_some() is complete.
Refer the Example section (example 2) of this msdn document
Here,
const char* someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);
This will not work as, the temporary object will be freed on the first statement itself. someMeaningfulName will be garbage. If you feel that as lack of security, all I can say is:
That's how Microsoft does it!
You will always get somewhere into troubles if you use const char* for your local variables.
You will have the same with const char* someMeaningfulName = std::string("foo").c_str();
If you can you should declare your local variable like this :
i2a someMeaningfulName(x);
set_some_text(someMeaningfulName);
You can also consider adding a copy constructor to i2a to avoid sharing the buffer between two instances.