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.
Related
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.
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.
As an introduction, note that I am a Java programmer still getting used to the memory management issues in C++.
We have a base class which is used to encoded objects to a string of ASCII characters. Essentially, the class is using a stringstream class member to convert different datatypes to one long string, and then returns a char* to the caller which contains the encoded object data.
In testing for memory leaks, I am seeing that the implementation we are using seems prone to create memory leaks, because the user has to always remember to delete the return value of the method. Below is an excerpt of the relevant parts of the code:
char* Msg::encode()
{
// clear any data from the stringstream
clear();
if (!onEncode()) {
return 0;
}
// need to convert stringstream to char*
string encoded = data.str();
// need to copy the stringstream to a new char* because
// stringstream.str() goes out of scope when method ends
char* encoded_copy = copy(encoded);
return encoded_copy;
}
bool Msg::onEncode(void)
{
encodeNameValue(TAG(MsgTags::TAG_USERID), companyName);
encodeNameValue(TAG(MsgTags::TAG_DATE), date);
return true;
}
bool EZXMsg::encodeNameValue(string& name, int value)
{
if(empty(value))
{
return true;
}
// data is stringstream object
data << name << TAG_VALUE_SEPARATOR << value << TAG_VALUE_PAIRS_DELIMITER;
return true;
}
char* copy(string& source) {
char *a=new char[source.length() +1];
a[source.length()]=0;
memcpy(a,source.c_str(),source.length());
return a;
}
UPDATE
Well - I should have been more accurate about how the result of encode() is consumed. It is passed to boost:async_write, and program is crashing because I believe the string goes out of scope before async_write complete. It seems like I need to copy the returned string to a class member which is alive for life time of the class which sends the message (?).
This is the way the encode() method is actually used (after I changed the return value of to string):
void iserver_client::send(ezx::iserver::EZXMsg& msg) {
string encoded = msg.encode();
size_t bytes = encoded.length();
boost::asio::async_write(socket_, boost::asio::buffer(encoded, bytes), boost::bind(&iserver_client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
It looks like the proper way to do this is to maintain a queue/list/vector of the strings to async write. As noted here (and also in the boost chat_client sample). (But that is a separate issue.)
For this question:
in your copy function you return a pointer to a heap memory!So user maybe create memory leak,I think you can not use this copy function,you can do just like this in your encode func:
return data.str();
If you want to get a char*, you can use the member function of string:c_str(),
just like this:
string ss("hello world");
const char *p = ss.c_str();
If you use a stack string object you will not create memory leak,
You could just return a std::string. You have one there anyway:
string Msg::encode()
{
// clear any data from the stringstream
clear();
if (!onEncode()) {
return string{};
}
return data.str();
}
Then the caller would look like:
Msg msg;
msg.userID = 1234;
send(msg.encode().c_str());
The only way of achieving "automatic" deletion is with a stack variable (at some level) going out of scope. In fact, this is in general the only way of guaranteeing deletion even in case of an exception, for example.
As others mentioned std::string works just fine, since the char * is owned by the stack-allocated string, which will delete the char *.
This will not work in general, for example with non char * types.
RAII (Resource Acquisition is Initialization) is a useful idiom for dealing with such issues as memory management, lock acquisition/release, etc.
A good solution would be to use Boost's scoped_array as follows:
{
Msg msg;
msg.userID = 1234;
scoped_array<char> encoded(msg.encode());
send(encoded.get());
// delete[] automatically called on char *
}
scoped_ptr works similarly for non-array types.
FYI: You should have used delete[] encoded to match new char[source.length() +1]
While using a std::string works adequately for your specific problem, the general solution is to return a std::unique_ptr instead of a raw pointer.
std::unique_ptr<char[]> Msg::encode() {
:
return std::unique_ptr<char[]>(encoded_copy);
}
The user will then get a new unique_ptr when they call it:
auto encoded = msg.encode();
send(encoded.get());
and the memory will be freed automatically when encoded goes out of scope and is destroyed.
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
Class:
class myclass {
public:
myclass(void);
const char* server;
private:
char pidchar[6];
int pidnum;
};
The function
myclass parseINI(const char* file)
{
myclass iniOptions;
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(file);
const char* server = ini.GetValue("", "server", "");
iniOptions.server = server;
std::cout << server << "\n"; // Prints the correct value here
fflush(stdout);
return iniOptions;
}
Calling it from the main function
int _tmain(int argc, TCHAR* argv[])
{
myclass options;
options = parseINI("myapp.ini");
std::cout << options.server << "\n"; // It prints junk here
return 0;
}
What did I do wrong?
The const char* returned by GetValue() probably belonged to the ini object. When you exited the parseIni() function, ini went out of scope and was destroyed, which could mean your pointer is no longer valid.
Try using a std::string for the server member type instead of const char*.
It looks like you are using memory that is released when CSimpleIniA goes out of scope in parseINI.
const char* server = ini.GetValue("", "server", "");
iniOptions.server = server;
Copy the value that is returned into a new memory block before you return from the parseINI function.
string server = ini.GetValue("", "server", "");
iniOptions.server = new char[server.length() + 1];
std::copy(server.begin(), server.end(), iniOptions.server);
iniOptions.server[server.length()] = 0;
const char* server = ini.GetValue("", "server", "");
This value is falling out of scope when the function terminates, so when you assign the value of that pointer to your object's server pointer, the place in memory they point to is having its memory freed off the stack at the end of the function, and it's then overtaken by other things.
Using a std::string or even just a char[] will be preferred to just fix the problem with the least amount of changes, as they will by assigned the actual value and not a location in memory like pointers.
What you really should do is look up referential transparency, though. That will prevent problems like this from occurring ever again
I's guess that the lifetime of the data pointed to by the char* returned from CSimpleIniA::GetValue() is the same as the CSimpleIni object itself. So when ini is destructed, the pointer returned from GetValue() becomes invalid. (I've never used CSimpleIni, and haven't looked at the docs carefully enough to know for sure, but that's what the behavior points to).
I'd suggest changing myclass::server to be a std:string object and set it using something like:
iniOptions.server = std::string(server);
which will give the myclass::server object it's own copy of the string data.
The way you are using class as a function returned data type in C++ is totally wrong.
In C++ there are 2 kinds of data type: value type, reference type.
class belongs to second one; From a function you can return a value type data or a pointer of any data.But you cann't retun a entity of a reference type. Because a entity of a reference type will be released right after the code reached out of the scope which the entity is defined.
You can do in either way:
1:
define parseINI as:
myclass* parseINI(const char* file)
{
myclass* iniOptions = new myclass();
........
return iniOptions;
}
and then use it like this:
myclass* options = parseINI("myapp.ini");
2:
define parseINI as:
void parseINI(myclass& options, const char* file)
{
........//asigne value to options's members
}
and then use it like this:
myclass options;
parseINI(options,"myapp.ini");
3:
Do what you did, but add a asignment method (operator=) to myclass
The problem is that the local variable server points to a character buffer returned by ini.GetValue(), which is destroyed when paraseINI() returns.
One way to fix this is to allocate a new buffer yourself and copy the characters.
const char* server = ini.GetValue("", "server", "");
int length = strlen(server) + 1; // length of the string +1 for the NULL character.
delete [] iniOptions.server; // free the old buffer
iniOptions.server = new char[length]; // allocate your own buffer
strncpy(iniOptions.server, server, length); // copy the characters
For this to work you have to make myclass::server non-const, and you have to initialize it to NULL in the constructor and delete it in the destructor.
A better way to deal with this situation would be use std::string instead of char * for muclass::server. This way std::string would take care of memory management for you, and the code would be exception-safe.
If you make muclass::server an std::string, then you simply do
const char* server = ini.GetValue("", "server", "");
iniOptions.server = std::string(server);
And you do not have to do anything with it in the constructor or the destructor.
iniOptions is located on the stack and disposed automatically when the function returns. You should allocate it on heap using new()