Manage memory C++ - 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.

Related

Error when instantiating a class which has an attribute with generic types [duplicate]

Given:
char test[] = "bla-bla-bla";
Which of the two is more correct?
char *test1 = malloc(strlen(test));
strcpy(test1, test);
or
char *test1 = malloc(sizeof(test));
strcpy(test1, test);
This will work on all null-terminated strings, including pointers to char arrays:
char test[] = "bla-bla-bla";
char *test1 = malloc(strlen(test) + 1);
strcpy(test1, test);
You won't get the correct size of the array pointed to by char* or const char* with sizeof. This solution is therefore more versatile.
Neither:
#include <string.h>
char *mine = strdup(test);
You should use strlen, because sizeof will fail silently if you change test to be a run-time defined string. This means that strlen is a far safer idea than sizeof as it will keep working.
char test[]="bla-bla-bla";
char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character
strcpy(test1, test);
I think sizeof is the correct one. Reason behind that is strlen(str) will give you length of the string( excluding the terminating null). And if you are using strcpy, it actually copy the whole string including the terminating null, so you will allocate one byte less if you use strlen in malloc. But sizeof gives the size of the string pointed by test, including the terminating null, so you will get correct size malloc chunk to copy the string including the terminating null.
1) definitely causes UB
2) may cause UB (if malloc fails)
I'd go with 2) as there is a better chance of the construct working as intended; or even better I'd write a version that works as intended (without UB) in all situations.
Edit
Undefined Behaviour in 1)
test1 will have space for the characters in test, but not for the terminating '\0'. The call to strcpy() will try to write a '\0' to memory that does not belong to test1, hence UB.
Undefined Behaviour in 2)
If the call to malloc() fails to reserve the requested memory, test1 will be assigned NULL. Passing NULL to strcpy() invokes UB.
The return value of calls to malloc() (and calloc() and friends) should always be tested to ensure the operation worked as expected.
(1) with strlen but not adding 1 is definitely incorrect. If you add 1, it would have the added benefit that it also works for pointers, not just arrays.
On the other hand, (2) is preferred as long as your string is actually an array, as it results in a compile-time constant, rather than a call to strlen (and thus faster and smaller code). Actually a modern compiler like gcc can probably optimize the strlen out if it knows the string is constant, but it may be hard for the compiler to determine this, so I'd always use sizeof when possible.
If it is a critical path, sizeof has advantage over strlen as it has an O(1) complexity which can save CPU cycles.

Why does returning a malloc'd pointer here result in "HEAP CORRUPTION" on free?

note: please suppress comments about "C++? Use std::string!". This question is using C strings but is more about memory management than strings in general.
I have this function
char* strclone( char* src )
{
char* dst = (char*)malloc(strlen(src+1));
strcpy(dst,src);
return dst;
}
The function should work to allocate a new pointer (in strclone), write the string in src to it, and return the address of the new string.
However, when the string is freed, some time later in the program:
str = strclone( some_str_variable );
// ..code..
free( str ) ; //! ERROR!
The error reads:
Debug Error!
Program: C:\...
HEAP CORRUPTION DETECTED: after Normal block (#39713) at 0x090CC448.
CRT detected that the application wrote to memory after end of heap buffer.
The error occurs at the line where I call free( str ) in the program. If I change the assignment of str to this:
str = (char*)malloc( strlen( some_string_variable ) +1);
strcpy( str, some_string_variable ) ;
//...
free( str ) ; //fine now
Then there is no bug, the program functions perfectly.
Why does the strclone function not work as expected?
I believe that the problem is that you've written
(char*)malloc(strlen(src+1));
Notice that in the call to strlen, you have written
strlen(src + 1)
instead of
strlen(src) + 1
This first line says "the length of the string starting one character past src," which is the length of the string minus one (or total garbage if the string is empty). The second one is the one you want - the length of the string plus one for the null terminator. If you use the first version, then in the line
strcpy(dst,src);
You will end up writing past the end of the buffer, leading to the dreaded Undefined Behavior. In your case, this was manifesting itself with a heap corruption error when you try to free the block, which makes sense because you have indeed corrupted the heap!
Try moving the +1 out of the parentheses and see if it fixes things.
Alternatively, most compilers ship with a nonstandard function called strdup that does exactly what your above function attempts to do. You might want to consider just using that instead.
Hope this helps!
strlen(src+1) is not the same as strlen(src)+1. So you are overwriting the bounds of your array by two elements when you do to the strcpy.
So I think the following is justified: C++? Use std::string!
I believe you should have typed
char* dst = (char*)malloc(strlen(src) + 1);
instead of
char* dst = (char*)malloc(strlen(src+1));
The error happens because you are actually writing past the allocated memory.
change your malloc line to this:
char* dst = (char*)malloc(strlen(src)+1);
Because in your original implementation, you're advancing the pointer by 1, and then you pass that to strlen(), which will give you the lenght of the string-1. Since you also need the NULL at the end, you're actually off-by-2.
Try this:
malloc(strlen(src)+1);

How to add a null character to the end of a string?

I start of with a
memcpy(g->db_cmd,l->db.param_value.val,l->db.param_value.len);
which contains the value "function" however I want a null character to be appended like "function'\0'" I've tried a
memcpy(&g->db_cmd[l->db.param_value.len],0,1);
This crashes the program. I've tried memset also
memset(&g->db_cmd[l->db.param_value.len],0,1);
This doesnt work. Any idea?
g->db_cmd[l->db.param_value.len] = 0;
assuming you have allocated space for that.
First off, C (and C++) is not dynamic like you know it from Java, C#, PHP and others. When you are presented with a string in C, the string is pretty much static in length.
To make the answer simpler, lets redefine your variables:
g->db_cmd will be called dest,
l->db.param_value.val will be called src, and
l->db.param_value.len will be called len.
You should allocate a new string of size len plus one (for the extra null).
Allocate a new dest:
dest = calloc(sizeof(char), len + 1);
calloc allocates an array of chars as long as len plus one. After calloc() has allocated the array it fills it with nulls (or \0) thus you automatically will have a null appended to your deststring.
Next, copy the src to dest with strncpy:
strncpy(dest, src, len);
To convert this back to your variable names:
g->db_cmd = calloc(sizeof(char), l->db.param_value.len + 1);
strncpy(g->db_cmd, l->db.param_value.val, l->db.param_value.len);
If you want string-copying semantics, why not use a string-copying function?
Strings are by default null-terminated.
If you want a to ad an extra NULL at the end you can write "String\0"
or db_cmd[len]='\0'
If the source you're copying from also contains a NULL terminated string use
memcpy( g->db_cmd, l->db.param_value.val, l->db.param_value.len + 1 );
Otherwise you'll have to add the terminator yourself.
g->db_cmd[l->db.param_value.len] = '\0';
Of course, you need to ensure that the destination has enough room for this character.
memcpy takes two pointers, and an integer. In the lines that you say are crashing, you pass it a pointer, and two integers. The code cannot dereference the second argument (0).
If you really really want to use memcpy, you have to have a pointer to a zero
char zero = 0;
memcpy(&g->db_cmd[l->db.param_value.len], &zero , 1);
But I would really suggest pyroscope's answer. It's faster, and clearer.

Memcpy, string and terminator

I have to write a function that fills a char* buffer for an assigned length with the content of a string. If the string is too long, I just have to cut it. The buffer is not allocated by me but by the user of my function. I tried something like this:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
//buffer[length]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
my question is about the terminator: should it be there or not? This function is used in a much wider code and sometimes it seems I get problems with strange characters when the string needs to be cut.
Any hints on the correct procedure to follow?
A C-style string must be terminated with a zero character '\0'.
In addition you have another problem with your code - it may try to copy from beyond the end of your source string. This is classic undefined behavior. It may look like it works, until the one time that the string is allocated at the end of a heap memory block and the copy goes off into a protected area of memory and fails spectacularly. You should copy only until the minimum of the length of the buffer or the length of the string.
P.S. For completeness here's a good version of your function. Thanks to Naveen for pointing out the off-by-one error in your terminating null. I've taken the liberty of using your return value to indicate the length of the returned string, or the number of characters required if the length passed in was <= 0.
int writebuff(char* buffer, int length)
{
string text="123456789012345";
if (length <= 0)
return text.size();
if (text.size() < length)
{
memcpy(buffer, text.c_str(), text.size()+1);
return text.size();
}
memcpy(buffer, text.c_str(), length-1);
buffer[length-1]='\0';
return length-1;
}
If you want to treat the buffer as a string you should NULL terminate it. For this you need to copy length-1 characters using memcpy and set the length-1 character as \0.
it seems you are using C++ - given that, the simplest approach is (assuming that NUL termination is required by the interface spec)
int writebuff(char* buffer, int length)
{
string text = "123456789012345";
std::fill_n(buffer, length, 0); // reset the entire buffer
// use the built-in copy method from std::string, it will decide what's best.
text.copy(buffer, length);
// only over-write the last character if source is greater than length
if (length < text.size())
buffer[length-1] = 0;
return 1; // eh?
}
char * Buffers must be null terminated unless you are explicitly passing out the length with it everywhere and saying so that the buffer is not null terminated.
Whether or not you should terminate the string with a \0 depends on the specification of your writebuff function. If what you have in buffer should be a valid C-style string after calling your function, you should terminate it with a \0.
Note, though, that c_str() will terminate with a \0 for you, so you could use text.size() + 1 as the size of the source string. Also note that if length is larger than the size of the string, you will copy further than what text provides with your current code (you can use min(length - 2, text.size() + 1/*trailing \0*/) to prevent that, and set buffer[length - 1] = 0 to cap it off).
The buffer allocated in main is leaked, btw
my question is about the terminator: should it be there or not?
Yes. It should be there. Otherwise how would you later know where the string ends? And how would cout would know? It would keep printing garbage till it encounters a garbage whose value happens to be \0. Your program might even crash.
As a sidenote, your program is leaking memory. It doesn't free the memory it allocates. But since you're exiting from the main(), it doesn't matter much; after all once the program ends, all the memory would go back to the OS, whether you deallocate it or not. But its good practice in general, if you don't forget deallocating memory (or any other resource ) yourself.
I agree with Necrolis that strncpy is the way to go, but it will not get the null terminator if the string is too long. You had the right idea in putting an explicit terminator, but as written your code puts it one past the end. (This is in C, since you seemed to be doing more C than C++?)
int writebuff(char* buffer, int length){
char* text="123456789012345";
strncpy(buffer, text, length);
buffer[length-1]='\0';
return 1;
}
It should most defiantly be there*, this prevents strings that are too long for the buffer from filling it completely and causing an overflow later on when its accessed. though imo, strncpy should be used instead of memcpy, but you'll still have to null terminate it. (also your example leaks memory).
*if you're ever in doubt, go the safest route!
First, I don't know whether writerbuff should terminate the string or not. That is a design question, to be answered by the person who decided that writebuff should exist at all.
Second, taking your specific example as a whole, there are two problems. One is that you pass an unterminated string to operator<<(ostream, char*). Second is the commented-out line writes beyond the end of the indicated buffer. Both of these invoke undefined behavior.
(Third is a design flaw -- can you know that length is always less than the length of text?)
Try this:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
buffer[length-1]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
In main(), you should delete the buffer you allocated with new., or allocate it statically (char buf[10]). Yes, it's only 10 bytes, and yes, it's a memory "pool," not a leak, since it's a one-time allocations, and yes, you need that memory around for the entire running time of the program. But it's still a good habit to be into.
In C/C++ the general contract with character buffers is that they be null-terminiated, so I would include it unless I had been explicitly told not to do it. And if I did, I would comment it, and maybe even use a typedef or name on the char * parameter indicating that the result is a string that is not null terminated.

Is there a safe version of strlen?

std::strlen doesn't handle c strings that are not \0 terminated. Is there a safe version of it?
PS I know that in c++ std::string should be used instead of c strings, but in this case my string is stored in a shared memory.
EDIT
Ok, I need to add some explanation.
My application is getting a string from a shared memory (which is of some length), therefore it could be represented as an array of characters. If there is a bug in the library writing this string, then the string would not be zero terminated, and the strlen could fail.
You've added that the string is in shared memory. That's guaranteed readable, and of fixed size. You can therefore use size_t MaxPossibleSize = startOfSharedMemory + sizeOfSharedMemory - input; strnlen(input, MaxPossibleSize) (mind the extra n in strnlen).
This will return MaxPossibleSize if there's no \0 in the shared memory following input, or the string length if there is. (The maximal possible string length is of course MaxPossibleSize-1, in case the last byte of shared memory is the first \0)
C strings that are not null-terminated are not C strings, they are simply arrays of characters, and there is no way of finding their length.
If you define a c-string as
char* cowSays = "moo";
then you autmagically get the '\0' at the end and strlen would return 3. If you define it like:
char iDoThis[1024] = {0};
you get an empty buffer (and array of characters, all of which are null characters). You can then fill it with what you like as long as you don't over-run the buffer length. At the start strlen would return 0, and once you have written something you would also get the correct number from strlen.
You could also do this:
char uhoh[100];
int len = strlen(uhoh);
but that would be bad, because you have no idea what is in that array. It could hit a null character you might not. The point is that the null character is the defined standard manner to declare that the string is finished.
Not having a null character means by definition that the string is not finished. Changing that will break the paradigm of how the string works. What you want to do is make up your own rules. C++ will let you do that, but you will have to write a lot of code yourself.
EDIT
From your newly added info, what you want to do is loop over the array and check for the null character by hand. You should also do some validation if you are expecting ASCII characters only (especially if you are expecting alpha-numeric characters). This assumes that you know the maximum size.
If you do not need to validate the content of the string then you could use one of the strnlen family of functions:
http://msdn.microsoft.com/en-us/library/z50ty2zh%28v=vs.80%29.aspx
http://linux.about.com/library/cmd/blcmdl3_strnlen.htm
size_t safe_strlen(const char *str, size_t max_len)
{
const char * end = (const char *)memchr(str, '\0', max_len);
if (end == NULL)
return max_len;
else
return end - str;
}
Yes, since C11:
size_t strnlen_s( const char *str, size_t strsz );
Located in <string.h>
Get a better library, or verify the one you have - if you can't trust you library to do what it says it will, then how the h%^&l do you expect your program to?
Thats said, Assuming you know the length of the buiffer the string resides, what about
buffer[-1+sizeof(buffer)]=0 ;
x = strlen(buffer) ;
make buffer bigger than needed and you can then test the lib.
assert(x<-1+sizeof(buffer));
C11 includes "safe" functions such as strnlen_s. strnlen_s takes an extra maximum length argument (a size_t). This argument is returned if a null character isn't found after checking that many characters. It also returns the second argument if a null pointer is provided.
size_t strnlen_s(const char *, size_t);
While part of C11, it is recommended that you check that your compiler supports these bounds-checking "safe" functions via its definition of __STDC_LIB_EXT1__. Furthermore, a user must also set another macro, __STDC_WANT_LIB_EXT1__, to 1, before including string.h, if they intend to use such functions. See here for some Stack Overflow commentary on the origins of these functions, and here for C++ documentation.
GCC and Clang also support the POSIX function strnlen, and provide it within string.h. Microsoft too provide strnlen which can also be found within string.h.
You will need to encode your string. For example:
struct string
{
size_t len;
char *data;
} __attribute__(packed);
You can then accept any array of characters if you know the first sizeof(size_t) bytes of the shared memory location is the size of the char array. It gets tricky when you want to chain arrays this way.
It's better to trust your other end to terminate it's strings or roll your own strlen that does not go outside the bounderies of the shared memory segment (providing you know at least the size of that segment).
If you need to get the size of shared memory, try to use
// get memory size
struct shmid_ds shm_info;
size_t shm_size;
int shm_rc;
if((shm_rc = shmctl(shmid, IPC_STAT, &shm_info)) < 0)
exit(101);
shm_size = shm_info.shm_segsz;
Instead of using strlen you can use shm_size - 1 if you are sure that it is null terminated. Otherwise you can null terminate it by data[shm_size - 1] = '\0'; then use strlen(data);
a simple solution:
buff[BUFF_SIZE -1] = '\0'
ofc this will not tell you if the string originally was exactly BUFF_SIZE-1 long or it was just not terminated... so you need xtra logic for that.
How about this portable nugget:
int safeStrlen(char *buf, int max)
{
int i;
for(i=0;buf[i] && i<max; i++){};
return i;
}
As Neil Butterworth already said in his answer above: C-Strings which are not terminated by a \0 character, are no C-Strings!
The only chance you do have is to write an immutable Adaptor or something which creates a valid copy of the C-String with a \0 terminating character. Of course, if the input is wrong and there is an C-String defined like:
char cstring[3] = {'1','2','3'};
will indeed result in unexpected behavior, because there can be something like 123#4x\0 in the memory now. So the result of of strlen() for example is now 6 and not 3 as expected.
The following approach shows how to create a safe C-String in any case:
char *createSafeCString(char cStringToCheck[]) {
//Cast size_t to integer
int size = static_cast<int>(strlen(cStringToCheck)) ;
//Initialize new array out of the stack of the method
char *pszCString = new char[size + 1];
//Copy data from one char array to the new
strncpy(pszCString, cStringToCheck, size);
//set last character to the \0 termination character
pszCString[size] = '\0';
return pszCString;
}
This ensures that if you manipulate the C-String to not write on the memory of something else.
But this is not what you wanted. I know, but there is no other way to achieve the length of a char array without termination. This isn't even an approach. It just ensures that even if the User (or Dev) is inserting ***** to work fine.