Free/delete strtok_r pointer before processing complete string? - c++

When trying to delete/free character ptr without being processed completely by strtok_r, its giving me stack trace error.
I know that one cannot free/delete a strtok_r char ptr in a regular way, without completing the whole strings separation process by strtok_r func.
Can anyone tell me how to free a char ptr, when its under process by strtok_r?
char *data = new char[temp->size()+1];//temp is of type string
copy(temp->begin(),temp->end(),data);
data[temp->size()]='\0';
count = 0;
while(pointData != NULL)
{
if(count == 0)
pointData = strtok_r(data,":",&data);
else
pointData = strtok_r(NULL,":",&data);
if(count == 5)//some condition to free data
delete[] data;// this produces stack trace error
cout<<pointdata<<endl;
count++;
}

Because strtok_r is advancing "data" as it goes, which means that it is no longer pointing at the address of the allocation; you need to keep a "freedata" pointer or the like around:
char *data, *freedata;
freedata = data = new char[temp->size()+1];
// do yer stuffz here
delete[] freedata;

The context passed to strtok_r in the third argument should be a different pointer to the string you want to separate. Try:
char *context;
....
pointData = strtok_r(data,":",&context);
else
pointData = strtok_r(NULL,":",&context);
I don't believe you need to initialise it before you pass it in.

The only pointers you may ever pass to free are those obtained by malloc, or those obtained from functions which are specified to return a pointer to memory "as if" obtained by malloc. strtok_r does not return a pointer to a string "as if obtained by malloc", so you may not call free on it. If you read the specification for this function, it returns a pointer to character in your input string, which has been potentially modified to clobber a separator with a null terminator.

Related

Char passing to other function best practice

I want to pass string to second function where it fills the character array and gives the value back. In the first function I want to take the string length after second function fills it.
first step
Planning to pass the character array
char data[10]="";
GetData(data); // Here Iam doing memset value to data
strlen(data);
second step
Planning to pass the character pointer
char *data;
GetData(data); // what I should do
strlen(data);
Can someone suggest which is the best practice
You want to use std::string, something like:
std::string data;
void GetData(std::string& str);
passing by non-const reference allows GetData to alter str.
Ideally the character pointer should be owned by the caller, and should take care of allocation (if possible, or callee has to do that on behalf of the caller) and deallocation
char *data = (char *) NULL; // should initialize to know allocated or not
the prototype of the call, GetData should be:
void GetData(char *& d); // pointer passed as reference
Within GetData, d shoud be allocated as:
d = new char[size]; //size should be appropriately decided including null terminating character
for example, if you wish to store a "hello" say, d should be allocated as :
d = new char[5+1]; // example
once done, in the caller, you must deallocate as:
if (data) delete [] data;
data = (char *) NULL;
The "classic", C-compatible method in Windows (where Visual C++ is most used) is to have a function that takes the buffer size as argument, and returns the size or length of data copied. Example:
//Inputs:
// buffer: [out/opt] If not null, write data here.
// size: [in] Buffer size including null terminator, ignored if buffer is null.
//Outputs:
// buffer: The data.
// Return Value: Length of data written to the buffer, without null terminator.
int GetData(char *buffer, size_t bufferSize);
This allows calling the function with a null buffer to obtain the length to allocate, allocate the data, and call the function again.
However, it's not very C++ and it's error-prone. Passing a pointer/reference to the pointer to allocate is better from a language standpoint, but has its drawbacks when crossing a DLL boundary, where it's recommended that any data allocated by a DLL be deallocated by the same DLL (preventing the use of ordinary smart pointers).

Manage memory C++

I have create these simple function.
char* tmp = new char[len];
strncpy(tmp,str+start,len);
int ret = atoi(tmp);
delete []tmp;
return ret;
I have a problem with memory managment.
When I read ret variable, the value is null. If I remove the instruction "delete []tmp;" the value is correct but the memory fast increase (because I don't release the memory).
Any ideas?
Thanks
From man strncpy: The strncpy() function is similar than strcpy, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
Check your str variable length and verify this null terminating condicion on strncpy
There are a few problems with atoi, one of them is that it doesn't have any kind of validation that the string you pass is really a number. Instead you might want to use strtol instead.
Also note that strncpy might not terminate the string in some cases. And that you might want to allocate one extra character (len + 1) for the terminator.
strncpy fills up the target array with '\0's once the end of the source is reached.
atoi expects a null terminated c-string, means an array of characters that ends with a '\0'.
Therefore you have to create an array with a size of len + 1, the strncpy function will the automatically null-terminate your target array.
What you could do is have the buffer be allocated from outside the function, and pass the tmp argument as an array. A better approach though, is to allocate an object. These get destructed as long as you don't use the new keyword. std::string would be perfect in this scenario.
Make sure tmp is terminated with a '\0'
Hard to tell what's wrong since str and len are not shown.
This function could be a lot simpler:
int ret = atoi(str + start);
return ret;
BTW, ret is an int and NULL is usually referred to pointers.

C++: How to use new to find store for function return value?

I'm reading the 3rd edition of The C++ Programming Language by Bjarne Stroustrup and attempting to complete all the exercises. I'm not sure how to approach exercise 13 from section 6.6, so I thought I'd turn to Stack Overflow for some insight. Here's the description of the problem:
Write a function cat() that takes two C-style string arguments and
returns a single string that is the concatenation of the arguments.
Use new to find store for the result.
Here's my code thus far, with question marks where I'm not sure what to do:
? cat(char first[], char second[])
{
char current = '';
int i = 0;
while (current != '\0')
{
current = first[i];
// somehow append current to whatever will eventually be returned
i++;
}
current = '';
i = 0;
while (current != '\0')
{
current = second[i];
// somehow append current to whatever will eventually be returned
i++;
}
return ?
}
int main(int argc, char* argv[])
{
char first[] = "Hello, ";
char second[] = "World!";
? = cat(first, second);
return 0;
}
And here are my questions:
How do I use new to find store? Am I expected to do something like std::string* result = new std::string; or should I be using new to create another C-style string somehow?
Related to the previous question, what should I return from cat()? I assume it will need to be a pointer if I must use new. But a pointer to what?
Although the problem doesn't mention using delete to free memory, I know I should because I will have used new to allocate. Should I just delete at the end of main, right before returning?
How do I use new to find store? Am I expected to do something like std::string* result = new std::string; or should I be using new to create another C-style string somehow?
The latter; the method takes C-style strings and nothing in the text suggests that it should return anything else. The prototype of the function should thus be char* cat(char const*, char const*). Of course this is not how you’d normally write functions; manual memory management is completely taboo in modern C++ because it’s so error-prone.
Although the problem doesn't mention using delete to free memory, I know I should because I will have used new to allocate. Should I just delete at the end of main, right before returning?
In this exercise, yes. In the real world, no: like I said above, this is completely taboo. In reality you would return a std::string and not allocate memory using new. If you find yourself manually allocating memory (and assuming it’s for good reason), you’d put that memory not in a raw pointer but a smart pointer – std::unique_ptr or std::shared_ptr.
In a "real" program, yes, you would use std::string. It sounds like this example wants you to use a C string instead.
So maybe something like this:
char * cat(char first[], char second[])
{
char *result = new char[strlen(first) + strlen(second) + 1];
...
Q: How do you "append"?
A: Just write everything in "first" to "result".
As soon as you're done, then continue by writing everything in "second" to result (starting where you left off). When you're done, make sure to append '\0' at the end.
You are supposed to return a C style string, so you can't use std::string (or at least, that's not "in the spirit of the question"). Yes, you should use new to make a C-style string.
You should return the C-style string you generated... So, the pointer to the first character of your newly created string.
Correct, you should delete the result at the end. I expect it may be ignored, as in this particular case, it probably doesn't matter that much - but for completeness/correctness, you should.
Here's some old code I dug up from a project of mine a while back:
char* mergeChar(char* text1, char* text2){
//Find the length of the first text
int alen = 0;
while(text1[alen] != '\0')
alen++;
//Find the length of the second text
int blen = 0;
while(text2[blen] != '\0')
blen++;
//Copy the first text
char* newchar = new char[alen + blen + 1];
for(int a = 0; a < alen; a++){
newchar[a] = text1[a];
}
//Copy the second text
for(int b = 0; b < blen; b++)
newchar[alen + b] = text2[b];
//Null terminate!
newchar[alen + blen] = '\0';
return newchar;
}
Generally, in a 'real' program, you'll be expected to use std::string, though. Make sure you delete[] newchar later!
What the exercise means is to use new in order to allocate memory. "Find store" is phrased weirdly, but in fact that's what it does. You tell it how much store you need, it finds an available block of memory that you can use, and returns its address.
It doesn't look like the exercise wants you to use std::string. It sounds like you need to return a char*. So the function prototype should be:
char* cat(const char first[], const char second[]);
Note the const specifier. It's important so that you'll be able to pass string literals as arguments.
So without giving the code out straight away, what you need to do is determine how big the resulting char* string should be, allocate the required amount using new, copy the two source strings into the newly allocated space, and return it.
Note that you normally don't do this kind of memory management manually in C++ (you use std::string instead), but it's still important to know about it, which is why the reason for this exercise.
It seems like you need to use new to allocate memory for a string, and then return the pointer. Therefore the return type of cat would be `char*.
You could do do something like this:
int n = 0;
int k = 0;
//also can use strlen
while( first[n] != '\0' )
n ++ ;
while( second[k] != '\0' )
k ++ ;
//now, the allocation
char* joint = new char[n+k+1]; //+1 for a '\0'
//and for example memcpy for joining
memcpy(joint, first, n );
memcpy(joint+n, second, k+1); //also copying the null
return joint;
It is telling you to do this the C way pretty much:
#include <cstring>
char *cat (const char *s1, const char *s2)
{
// Learn to explore your library a bit, and
// you'll see that there is no need for a loop
// to determine the lengths. Anything C string
// related is in <cstring>.
//
size_t len_s1 = std::strlen(s1);
size_t len_s2 = std::strlen(s2);
char *dst;
// You have the lengths.
// Now use `new` to allocate storage for dst.
/*
* There's a faster way to copy C strings
* than looping, especially when you
* know the lengths...
*
* Use a reference to determine what functions
* in <cstring> COPY values.
* Add code before the return statement to
* do this, and you will have your answer.
*
* Note: remember that C strings are zero
* terminated!
*/
return dst;
}
Don't forget to use the correct operator when you go to free the memory allocated. Otherwise you'll have a memory leak.
Happy coding! :-)

C++ - how to check if char* points to something valid?

I want to check if a char* points to a valid string...Can I check this variable...
char* c;
What I tried:
if(c == NULL) //c is not null
if(*c == '\0') //false
if(strlen(c) == 0) //exception
I think it is not possible to check a char* when it was not allocated and dont point to a valid string...
Truth is, you can't ever be sure a pointer is valid. Testing for NULL may give you certainty that it is invalid, but it doesn't guarantee any validity. That's one reason not to use this kind of thing in C++. A std::string is always in a valid state.
If the pointer is not NULL, there is no way of saying if the value of the pointer is valid or not.
c can point anywhere. This might be a null terminated string, a string without terminating null byte, any accessible binary data or any address that is not accessible. What exactly do you want to check for and why? If you want to differentiate between a valid string and a not-initialized, you would normally use NULL for the uninitialized case and check c==NULL. Accessing *c (strlen does this, too) is not OK if c is not a valid pointer. So a typical usecase would be like this:
// initializing to NULL
char *c = NULL;
// maybe setting value
if(condition)
c = strdup("mein string");
// cleanup
if(c != NULL) {
free(c);
c = NULL;
}
If you have an upper bound on the size of the string you expect:
char * c = new char[size];
then perhaps you can check if it terminates within the bound:
bool is_valid(char *c, size_t size) {
while (size--) if (*c) return true;
return false;
}
another way is encapsulating the char * within a class in the constructor, or to have a valid flag in such a class.
It depends on the O/S. Under Windows you have the IsBadXxxPtr() family of functions which will test for a pointer to valid memory, although they won't test if the pointer is to a valid instance of a particular type.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366713(v=vs.85).aspx
etc.

Converting a std::list to char*[size]

for some reason I cannot explain, every single item in the character array...is equal to the last item added to it...for example progArgs[0] through progArgs[size] contains the value of the last item.
I cannot figure out what I'm doing wrong for the life of me. Any suggestions?
int count = 0;
char *progArgs[commandList.size()]
for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
{
char item[strlen((*t).c_str())]; //create character string
strcpy(item, (*t).c_str()); //convert from const char to char
progArgs[count] = item;
count++;
}
edit:
Thanks for all the quick responses everyone...I see what you are talking about
You're assigning the same pointer (the address of the first element of the stack array item) to each element of progArgs, then repeatedly overwriting that memory. You can do:
progArgs[count] = strdup(t->c_str());
and get rid of the first two lines of the for body.
strdup allocates memory, so you will have to free each element with free later. Also, you were not allocating a character for the NUL-terminator. You need would strlen + 1. However, this is not an issue with strdup, since it allocates for you.
progArgs is an array of pointers to char.
You set each of these pointers to point to item. item is a local variable in the loop, so as soon as the loop exits, item no longer exists and the pointers are no longer valid[*]. However, in your C++ implementation, they all still point to the bit of memory which used to be the array item on the stack. This memory contains whatever it was last used for, which is the sequence of characters from the last string in the list.
If you want to copy a list of strings to an array, it would be better if possible to use an array of strings:
std::string progArgs[commandList.size()] // if your compiler has C99 VLAs as an extension
int count = 0;
for(std::list<std::string>::iterator t=commandList.begin(); t != commandList.end(); ++t) {
progArgs[count] = *t;
++count;
}
Or even better, use a vector instead of an array:
std::vector<std::string> progArgs(commandList.begin(), commandList.end());
[*] to be more precise, the scope of item is a single repeat of the loop, it's nominally "created" and "destroyed" each time around. But this doesn't do any work - on your C++ implementation the same region of memory is re-used each time, and there's no work needed to create or destroy an array of char on the stack.
item has scope local to the loop. The propArgs array therefore contains a bunch of stack-based pointers, likely all the same. You can examine how this works in the debugger, just step thru the loop twice and it should be clear what's going on.
By the time you exit the loop, the buffer addressed by the common pointer contains the most recently-copied c_str().
You could fix this by doing
char* item = new char[strlen((*t).c_str()) + 1];
but then you'd have to delete[] all the propArgs array entries when you exit the loop.
This code shows a fundamental lack of understanding of memory management such that further reading might be useful before restructuring the code. If the code used here was in only slightly more complex context than this example, it might just crash since any access of propArgs outside the loop would rely on an invalid (no longer in scope) item.
The char array item is local variable and is available only within the for loop.
Instead allocate it dynamically.
You're right:
for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
{
char item[strlen((*t).c_str())]; //create character string
...this does create an array, but it creates it on the stack, so when you reach the end of its scope, it gets destroyed.
strcpy(item, (*t).c_str()); //convert from const char to char
progArgs[count] = item;
count++;
}
...and this closing brace marks the end of its scope. That means you're creating a string, putting it into your array, then destroying it before you add the next one. Thanks to the fact that you're creating them all on the stack, each new one you create is being created in exactly the same place as the previous one, so it's no surprise that at the end of it all, you have a bunch of identical strings.
Perhaps it would be better if you told us what you're trying to accomplish here, so we can help you do that.
You're setting progArgs[count] to the same item every time!
int count = 0;
char *progArgs[commandList.size()]
for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
{
char * item = new char[strlen((*t).c_str()) + 1]; //create new character string
strcpy(item, (*t).c_str()); //convert from const char to char
progArgs[count] = item;
count++;
}
Then remember to call delete[] for each element in progArgs.
Personally, I'd create an array of string and convert to char * on the fly as needed.