Empty string when trying to convert const char * to NSString - c++

I have encountered a strange bug while trying to get a NSString from a const char *.
// in my obj c class
void myObjCMethod {
const char* charString = myCFunctionReturningConstCharPtr();
printf("%s \n", charString); // prints the correct string
// ...put a brakpoint here...
NSString * nsString1 = [NSString stringWithUTF8String:charString];
NSLog(#"%#", nsString1); // prints nothing
NSString * nsString2 = [NSString stringWithFormat:#"%s",charString];
NSLog(#"%#", nsString2); // prints nothing either
}
The const char coming from my c method prints nicely to the console. But trying to convert to NSString results in an empty string.
Now the weirdest thing is, that when I try to debug the code and set a breakpoint (as indicated above), my NSString suddenly becomes valid!
So what -- my mesurement changes the result? Sounds familiar from physics class long ago, but I doubt there is quantum mechanics involved here.
Note:
I have omitted the implementation of myCFunctionReturningConstCharPtr() for now, as it would add another layer of complexity that is probably not related to the present problem (There are multiple c++ libraries involved, the string has been converted from char pointer to std::string and back).
I've been banging my head against this for two days now, any help is appreciated very much! Thanks
EDIT:
The string initially comes from the struct SPODNode from PowerVR's Insider SDK.
There we have:
struct SPODNode {
PVRTchar8 *pszName;
// ...
}
With:
typedef char PVRTchar8;
In my code I do:
std::string MyCppClass::pvrNodeName() {
if (node && node->pszName) {
string stdName(node->pszName);
return stdName;
}
return string();
}
And finally in myCFunctionReturningConstCharPtr():
const char * myCFunctionReturningConstCharPtr() {
std::string stdString = myCppClassInstace->pvrNodeName()
return stdString.c_str();
}
I hope that helps!

The const char * is obtained by calling .c_str() on a std::string.
It is very likely that your program has Undefined Behavior, because you are returning a pointer to an array of character that gets deallocated when returning from function myCFunctionReturningConstCharPtr().
In fact, that const char* you return points to a character array that is encapsulated by a local std::string object; the destructor of the std::string object deallocates that array, and the destructor is invoked when the local object goes out of scope, i.e. when returning from the function.
Later attempts to dereference the pointer you receive result in Undefined Behavior, which means anything could happen. This includes your program seeming to run fine when being debugged, but not when running without the debugger attached.
You should have your function return (by value) an std::string, and then invoke c_str() on that returned value if you need to get the encapsulated C-string:
std::string charString = myCFunctionReturningConstCharPtr();
printf("%s \n", charString.c_str()); // prints the correct string

Related

Using String c_str() to return char*

I am working on some legacy code where I have to make some changes in the cpp file.The cpp file contains entire code in extern "c" block -
I updated a function that returns a char* .The code looks something like func1() below.
Since I use std::strring and stringstream I included the sstream and string header files before extern block.
The below function is called from both c and cpp files.So I cannot return std::string here -
char* func1(someStruct* pt){
std::strig nam = somefunc(pt);
//have to append some integer in particular format
std::stringstream ss;
ss<<nam<<pt->int1 ......;
nam = ss.str();
//More code here for returning char* based on queries - (a)
}
At one of the places where this function is called -
void otherFunc(.....){
//......
char* x = func(myptr);
if(based_on_some_condition){
char* temp = func3(x); //returns a char* to dynamically allocated array.
strcpy(x,temp); //copying (b)
}
//..........
}
Following is my query -
1) At (a) I can return char* in following 2 forms.I have to make a decision such that copying at (b) does not cause any undefined behavior -
i)Create a char array dynamically with size = nam.length()+10 (extra 10 for some work happening in func3).<br>
char* rtvalue = (char*)calloc(sizeof(char),nam.length()+10);
strcpy(rtvalue,nam.c_str());
return rtvalue;
And free(temp); in otherFunc() after strcpy(x,temp);
ii) Declare 'nam' as static std::string nam;
and simply return const_cast<char*>(nam.c_str());
Will defining 'nam' with static scope ensure that a correct return happen from function (ie no dangling pointer at 'x')?
More importantly, can I do this without worrying about modification happening at (b).
Which one is a better solution?
Problem is returning a char *. When you using C++ you should not use this type. This is not C! std::string or std::vector<char> should be used.
If you will use char * as return type in this kind of function it will end with undefined behavior (access to released memory) or memory leak.
If you will use static std::string nam; function will maintain internal state and this is always leads to trouble.
For example if you create threading functionality you will have undefined behavior. Even worse if you will use this function twice for some reason result of second call will have impact on result for first call (for example your coworker will use this function since he will not expect hiden side effects).
If you are designing some API which should be accessible from C code than you should design this API in different way. I do not know what kind of functionality you are providing by most probably you should something like this:
char *func1(someStruct* pt, char *result, int size){ // good name could be like this: appendStructDescription
std::strig nam = somefunc(pt);
//have to append some integer in particular format
std::stringstream ss;
ss<<nam<<pt->int1 ......;
nam = ss.str();
int resultSize = std::min(size - 1, nam.length());
memcpy(result, nam.c_str(), resultSize);
result[resultSize] = 0;
return result + resultSize;
}
This approach has big advantages: responsibility for a memory management goes to caller, user of the API understands what is expected.
It is true that you should return string, but if you absolutely need to return char*, first method is better. And don't forget free. Otherwise, expressions like strcmp(f(pt1), f(pt2)) would return unpredictable results.

Use a string as a char

I have been given this definitions, the function should return what is in info->phrase. However info->phrase can contain a string in which case I can only make it return the first char on info->phrase. Is there a way to make a string compatible with the char type? I am new to c++.
struct rep_info {
int num;
char *phrase;
};
I´ve tried few thing but get type errors, this was my latest attempt
char *phrase_info(rep_info info) {
char text[std::strlen(info->phrase) + 1];
text = info->phrase;
return text;
}
Since you said you have been given these definitions, let's fix the problem with the current setup first. Looking at your function, you are trying to copy into this local array (incorrectly I might add), and return this local variable. There are a number of things wrong with this, including the syntax and the fact that the local variable is destroyed when the function exits.
If you just need to get the value of the phrase member variable, the simplest solution would be to just access the member variable directly and return it:
char *phrase_info(rep_info info) {
return info.phrase; //since info is not a pointer, use the '.' accessor
}
If you mean to pass a pointer to the function, you would re-write it like this:
char *phrase_info(rep_info *info) {
return info->phrase;
}
But it seems like you feel the need to copy the contents of info->phrase into a new memory space? If so, then you would do something like this where you first allocate new memory and return this buffer:
char *phrase_info(rep_info *info) {
char *buf = new char[std::strlen(info->phrase) + 1];
std::strcpy(buf,info->phrase); //copies info->phrase into buf
return buf;
}
You would then need to use delete on the returned memory value to clean up the memory allocated by new, otherwise you will have a memory leak.
Overall, all the above solution would potentially solve the problem given some parameters you haven't made clear. To round this out, this should be written more like:
class rep_info {
private:
int num;
std::string phrase;
public:
rep_info(int n, std::string p) : num(n), phrase(p) {}
std::string get_phrase() { return phrase; }
// other functions
};
//later in the code
rep_info info(...);
info.get_phrase();
Ideally, you would wrap these member variables into their own object with corresponding member functions that can get and set these values. Moreover, for handling strings in C++, std::string is the preferred option for storing, copying, modifying, etc. strings over the older char * C-style string.

Strange output for luajit ffi function returning string

I have a function like the following returning a c-string from an another function returning a std::string.
const char* GetFilePath(const char* aFilename)
{
return FileSystem->GetFilePath(aFilename).c_str();
}
If I call this function from lua I only get garbage. If I modify the function to return for example a "Test" it works.
I think it is because the returned std::string's destructor will be called and therefore delets the string making the c-string invalid.
My question is how can I prevent this? How can I get this working?
UPDATE:
I expose this function to Lua with the following.
local ffi = require('ffi')
ffi.cdef[[
const char* GetFilePath(const char* aFilename)
]]
x = ffi.string(GetFilePath("Script.lua"))
io.write(x)
This code just prints some random garbage. But if I modify the C-Wrapper function to just to return a C-Style string I get the desired output.
Update 2:
For example if I do something like the following:
const char* GetFilePath(const char* aFilename)
{
return aFilename;
}
It works as expected. Also when I expose some other functions returning an const char*.
BUT if I do the following:
const char* GetFilePath(const char* aFilename)
{
return std::string(aFilename).c_str();
}
I get random garbage. My original C++-Function returns an std::string.
If you insist on using the luajit FFI for this instead of using the C api, you are going to have to write some more complicated C++.
The issue is that, any function that returns const char * in C++, cannot be generated by calling c_str() on a local or temporary std::string because it will become invalid before lua gets a chance to use it.
The simplest trick to get around this is to use a static local variable, which won't be destroyed right after the function returns.
const char* GetFilePath(const char* aFilename)
{
static std::string long_lived;
long_lived = FileSystem->GetFilePath(aFilename);
return long_lived.c_str();
}
There's some extra overhead here -- the long_lived string will be allocated until GetFilePath is called again, or your program ends. But these strings are small, so this overhead doesn't matter much.

const char *const changes because of a string (?)

Hello i am building a project and today after 500 lines of code i am going to shoot my self. Today i started a new class and some very strange things are happening:
class Target {
public:
Target(const int port);
virtual ~Target();
private:
const char* initialize_port(const int port) const;
const char *const port;
};
and cpp file:
Target::Target(const int port)
:
port(initialize_port(port))
{
cout<<this->port<<endl; //this cout 80
string test3="Target2";//when i replace with char * test3="Target2" then both couts in the constructor are working ok.
cout<<this->port<<endl; //this cout Target2!!!!!!
}
const char* Target::initialize_port(const int port) const {
string port_str = std::to_string(port);
const char* port_char=port_str.c_str();
return port_char; // OR/and when i replace with something like return "80" then both couts in the constructor are working ok.
}
Target::~Target() {
}
Like you can see in the cpp file, while the default constructor is being called it couts the "this->port", then i create a string, and then i print it again. How is it even possible to get a different response??
From netbeans:
80
Target2
RUN FINISHED; exit value 0; real time: 20ms; user: 0ms; system: 0ms
PS:When in the function initialize_port(const int port) i am giving a standard return, for example return "80"; everything is ok. When in the constructor i am replacing the string with char *, again everything is ok.
PS2:I know that i have some problems with my RAM. If someone will compile and there is no problem with the outputs (cout) please let me know.
Thanks in advance.
The problem comes from:
{
string port_str = std::to_string(port);
const char* port_char=port_str.c_str();
return port_char;
}
When the return happens, port_str is destroyed because it is a locale variable to that code block. Then port_char is a dangling pointer (a pointer that used to point to an object that has now been destroyed).
Using that pointer causes undefined behaviour and that explains your weird effects when you use the pointer.
To fix this, stop using raw pointers. The simplest fix is to use std::string instead.
The problem is that the return value of port_str.c_string() is only valid for the lifetime of port_str. Since that is allocated on the stack in initialize_port it becomes invalid once that function returns.
In your constructor, when you initialize the test3 string it ends up (mostly by chance) occupying the same memory as port_str did.
If you need to use a const char * you will need to allocate new memory for the string inside initialize_port (and deallocate it in your constructor!). Alternatively just stick with using std:string objects.

how to set char * value from std string (c_str()) not working

i dont know but this not working for me im getting garbege value when i try to set char * value from function that returns std string :
string foo()
{
string tmp ="dummy value";
return tmp;
}
char* cc = (char *) foo().c_str(); // if i remove the casting im getting error
// when i print the cc i get garbage
printf("%s",cc);
The lifetime of the data pointed to by cc is the same as the lifetime of the string it came from (at best - if you modify the string it's even shorter).
In your case, the return value of foo() is a temporary that is destroyed at the end of the initialization of cc.
To avoid the compilation error in char *cc = foo().c_str() you shouldn't cast to char*, you should switch to const char *cc, since const char* is what c_str() returns. That still doesn't solve the main problem, though.
The simplest fixes are:
printf("%s", foo().c_str()); // if you don't need the value again later
const string s = foo();
const char *cc = s.c_str(); // if you really want the pointer - since it's
// in the same scope as s, and s is const,
// the data lives as long as cc's in scope.
string s = foo();
printf("%s", s.c_str()); // if you don't store the pointer,
// you don't have to worry about it.
std::cout << foo(); // printf isn't bringing much to this party anyway.
The result of foo is a temporary object that gets destroyed by the end of char * cc = ... line. Store it in constant reference:
const string& cc = foo();
printf ("%s", cc.c_str());
Pass a memory location to foo() and have foo modify that:
void foo (string* _out_newStr)
{
_out_newStr->assign("dummy string"); //This is wrong -> _out_newStr = "dummy string";
return;
}
Then when you are using the "c_str()" function of the string object you will return a const char* value, as already pointed out.
The code-snippet invokes undefined behavior, because the temporary std::string created from the call is destroyed at the end of the expression but cc which is pointing to the destroyed object, is still used even after that.
How about:
printf("%s", foo.c_str() );
Or better still, forget about using character pointers.