I have a old program in which some library function is used and i dont have that library.
So I am writing that program using libraries of c++.
In that old code some function is there which is called like this
*string = newstrdup("Some string goes here");
the string variable is declared as char **string;
What he may be doing in that function named "newstrdup" ?
I tried many things but i dont know what he is doing ... Can anyone help
The function is used to make a copy of c-strings. That's often needed to get a writable version of a string literal. They (string literals) are itself not writable, so such a function copies them into an allocated writable buffer. You can then pass them to functions that modify their argument given, like strtok which writes into the string it has to tokenize.
I think you can come up with something like this, since it is called newstrdup:
char * newstrdup(char const* str) {
char *c = new char[std::strlen(str) + 1];
std::strcpy(c, str);
return c;
}
You would be supposed to free it once done using the string using
delete[] *string;
An alternative way of writing it is using malloc. If the library is old, it may have used that, which C++ inherited from C:
char * newstrdup(char const* str) {
char *c = (char*) malloc(std::strlen(str) + 1);
if(c != NULL) {
std::strcpy(c, str);
}
return c;
}
Now, you are supposed to free the string using free when done:
free(*string);
Prefer the first version if you are writing with C++. But if the existing code uses free to deallocate the memory again, use the second version. Beware that the second version returns NULL if no memory is available for dup'ing the string, while the first throws an exception in that case. Another note should be taken about behavior when you pass a NULL argument to your newstrdup. Depending on your library that may be allowed or may be not allowed. So insert appropriate checks into the above functions if necessary. There is a function called strdup available in POSIX systems, but that one allows neither NULL arguments nor does it use the C++ operator new to allocate memory.
Anyway, i've looked with google codesearch for newstrdup functions and found quite a few. Maybe your library is among the results:
Google CodeSearch, newstrdup
there has to be a reason that they wrote a "new" version of strdup. So there must be a corner case that it handles differently. like perhaps a null string returns an empty string.
litb's answer is a replacement for strdup, but I would think there is a reason they did what they did.
If you want to use strdup directly, use a define to rename it, rather than write new code.
The line *string = newstrdup("Some string goes here"); is not showing any weirdness to newstrdup. If string has type char ** then newstrdup is just returning char * as expected. Presumably string was already set to point to a variable of type char * in which the result is to be placed. Otherwise the code is writing through an uninitialized pointer..
newstrdup is probably making a new string that is a duplicate of the passed string; it returns a pointer to the string (which is itself a pointier to the characters).
It looks like he's written a strdup() function to operate on an existing pointer, probably to re-allocate it to a new size and then fill its contents. Likely, he's doing this to re-use the same pointer in a loop where *string is going to change frequently while preventing a leak on every subsequent call to strdup().
I'd probably implement that like string = redup(&string, "new contents") .. but that's just me.
Edit:
Here's a snip of my 'redup' function which might be doing something similar to what you posted, just in a different way:
int redup(char **s1, const char *s2)
{
size_t len, size;
if (s2 == NULL)
return -1;
len = strlen(s2);
size = len + 1;
*s1 = realloc(*s1, size);
if (*s1 == NULL)
return -1;
memset(*s1, 0, size);
memcpy(*s1, s2, len);
return len;
}
Of course, I should probably save a copy of *s1 and restore it if realloc() fails, but I didn't need to get that paranoid.
I think you need to look at what is happening with the "string" variable within the code as the prototype for the newstrdup() function would appear to be identical to the library strdup() version.
Are there any free(*string) calls in the code?
It would appear to be a strange thing do to, unless it's internally keeping a copy of the duplicated string and returning a pointer back to the same string again.
Again, I would ask why?
Related
I've been trying for the past hour in utter frustration, but no matter what I try, or look up, I can't find anything that's specific to CStrings.
So I have a function for a library I'm working on that goes like this (edited out the non-relevant bits from it)
char *String_set(char **string_one, char *string_two){
// Tests pointers to check if NULL, return NULL if one is
free(*string_one); // Free the pointer so as to not cause a leak.
*string_one = malloc(strlen(string_two) + 1); // Allocate string_one
memset(*string_one, 0, strlen(string_two) + 1); // Cleans the string
strcpy(*string_one, string_two); // Copy string_two into string_one by reference
return *string_one;
}
Now, I have also tried NOT freeing the *string_one, and instead reallocating the pointer to hold enough for string_two, THEN clearing it out (with memset), but both have the same result. Either A) Segmentation fault if a string literal was passed, or B) No change if a mutable string is passed.
The kicker (to me) is that I've added quite a few print statements to it to monitor the goings-on of the function, and if anything it confused me even more as I got output like this...
//Output before function is called. It outputs info about the string before function
String's value:
// Initialized it to "", so it's meant to be empty.
String's Memory Address: 0x51dd810
// Inside of function
String's value:
// Same value
String's Memory Address: 0x51dd810
// Same memory address
String_Two's Value: "Hello World"
// What I am attempting to replace it with.
// After operations in function, before return statement
Final String's Value: "Hello World"
// Gets set
Final String's memory address: 0x51dd950
// Different address
// After return
String's value:
// Nothing changed. Even after freeing the contents at memory address?
String's memory address: 0x51dd810
// Still same memory address ?
Then it fails my Unit test because the value did not change as expected. May I get an answer as to why? Now, I'm a bit of a newbie to C, but I figured that anything allocated on the heap is global in scope, hence accessible anywhere. Also modifiable anywhere as well. Why is it that, my changes did not go through at all? Why is it that the value of the string changes in the function but rolls back at the return of it? I know C is pass-by-value, but I figured passing the reference by value would work. How can I properly change the value of a string passed to a function, and what is wrong with my code?
Thank you in advance.
Edit: Gist of what should be runable code (remove the REVERSE, LOWERCASE, UPPERCASE lines)
Edit2: Updated GIST on mobile, May be some other errors, posted this in a hurry.
Edit3: Ideone of the... strangely working build. Strangely, this is also working on both Windows and Linux Virtual Machine, so the problem may not be there specifically... I'm honestly at a lost for words (disregarding the runtime error). I try to compile my project and run the tests over and over, and the code in ideone is word-for-word verbatim (although there's no runtime when I run it, strangely).
This is not a full answer, and I'm not sure this isn't becoming code-review, which is actually off-topic on SO. (Viewers please feel free to edit this answer if you find any additional flaws.)
String_Utils_concat() has no clean ownership semantics. If SELECTED(parameter, MODIFY), then it returns string_one (is literal in test), otherwise temp (mallocated). You cannot safely free result unless you remembered the value of parameter at time of call.
The code is very complex. Consider using strdup and asprintf.
Differences you see on platforms are probably due to different memory management schemes and different behavior of undefined behaviors.
Deep coupling of parameter is root of all troubles. Code can become less complex just by turning it inside-out. Can't provide a snippet, because all these string_xxx and parameter values, as well as the entire target, feel nonsense to me.
If you need a string library with duplicate/concat facilities, then:
char *strdup(const char *s); // already in libc
char *s; asprintf(&s, "%s%s", s1, s2); // already in libc
... After aggressive cleaning just for this case, your functions became mostly trivial:
// String_Utils_copy() eliminated as strdup() ('parameter' was not used)
char *
String_Utils_set(char **string_one, char *string_two)
{
free(*string_one);
return (*string_one = strdup(string_two));
}
char *
String_Utils_concat(char *string_one, char *string_two, int parameter)
{
char *temp; asprintf(&temp, "%s%s", string_one, string_two);
if (SELECTED(parameter, MODIFY)) {
String_Utils_set(&string_one, temp, NONE);
// i.e. 1) free(string_one);
// ^ this probably frees literal
// 2) string_one = strdup(temp);
free(temp);
return string_one;
// (what was the point at all?)
// entire thing is same as "return temp" except for freeing literal
}
return temp;
}
I hope there are some clues now...
Quick edit: as you're already allocating and copying here and there without a reason, I assume you're not in a very tight loop nor constrained otherwise. Then all interfaces should stick with widely-default "get const char *, return char * that should be freed" rule. I.e.
char *String_Utils_set(...); // throw it away
char *String_Utils_concat(const char *s1, const char *s2);
char *strdup(const char *s); // already in libc
char *s = String_Utils_concat("Hello, ", "World!");
printf("%s\n", s);
free(s); s = NULL;
char *s = strdup("Hello!");
printf("%s\n", s);
free(s); s = NULL;
With that clean and proper interface you may do whatever you meant by parameter just in-place, without any headaches.
this is what I have so far but I can't figure out what is wrong with it
void newCopy(char *s)
{
char newString = malloc(sizeof(int * strlen(s)));
newString = s;
return &newString;
}
void newCopy(char *s)
{
char newString = malloc(sizeof(int * strlen(s)));
First and second problems are here.
First is, You're assigning the return of malloc, which is a pointer, to a variable declared as char. The variable should be declared as char*.
Second is, your input to sizeof is wrong.
int * strlen(s) is nonsense and won't compile, because you're trying to multiply a type and an integer. You meant sizeof(int) (which is an integer) * strlen(s) (also an integer) which will compile.
You should use sizeof(char) instead of sizeof(int), since it is a string.
You should add 1 to the size, since strings in C need to be null terminated by an extra \0 that strlen does not report being part of the string length.
Putting it all together, sizeof(char)*(strlen(s)+1)
newString = s;
Third problem is here. = is not a magic operator - it assigns the value in the variable s (which is a pointer) to the value in the variable newString (which after fixing the above mistake, will also be a pointer). It does nothing beside that.
What you want to do instead is use strcpy, which is a function that copies the contents of one string (by following its pointer) to the contents of another string (by following its pointer). http://www.cplusplus.com/reference/cstring/strcpy/
return &newString;
Fourth and fifth problems are here.
Fourth is, You have declared the function as void and here you are trying to return a char*.
Fifth is, you are trying to return a pointer to something that was declared on the stack (a local variable). As soon as the function returns, anything on the stack for that function is trash and cannot be referenced anymore.
However, if you correctly make newString of type char*, all you need to do is return newString; And you correctly return a pointer by value which points into the heap (thanks to the earlier malloc).
}
Finally, judging by this code, I should inform you that C is not a newbie friendly language, where you can just type things that 'look like' what you want to happen and pray it works. If you're even slightly wrong your code will crash and you will have zero idea why, because you don't know the right way to do things. Either read a really good book on C and teach yourself everything from basic to advance step by step so you know how it all works, or pick up a more user friendly language.
I should start by pointing out that in my opinion, given the number and (especially) nature of the mistakes in this code, you probably need to get a good book on C.
Your newString = s; overwrites the pointer instead of copying the string into the space you just allocated. Thus, you lose the pointer to what you just allocating (leaking the memory) without making a copy. You probably want to use strcpy instead of direct assignment.
Your computation of the size you allocate isn't what you really want either. Typically, for a string of length N, you want to allocate N+1 bytes. You're currently attempting to allocat sizeof(int * strlen(s)) bytes, which shouldn't even compile.
A corrected version should be like:
char *newCopy(char *s)
{
if (s == NULL)
return NULL;
char *newString = malloc(strlen(s) + 1);
if (newString == NULL)
return NULL;
strcpy(newString, s);
return newString;
}
Is there a possibility that strcat can ever fail?
If we pass some incorrect buffer or string, then it might lead to memory corruption. But, apart from that is it possible that this function can return failure like strcat returning NULL even if destination string passed is Non-NULL? If no, why strcat has a return type specified at all?
I have just mentioned strcat as an example. But, this question applies to many string and memory related (like memcpy etc) functions. I just want to know the reasoning behind some of these seemingly "always successful" functions having return types.
Returning a pointer to the target string makes it easy to use the output in this sort of (perhaps not-so-clever) way:
int len = strlen(strcat(firstString, secondString));
Most of them go back to a time when C didn't include 'void', so there was no way to specify that it had no return value. As a result, they specified them to return something, even if it was pretty useless.
The implicit contract of these functions is the following: if you pass-in pointers to valid strings, then the functions will perform as advertised. Pass-in a NULL pointer, and the function may do anything (usually, it will raise a SIGSEGV). Given that the arguments are valid (i.e., point to strings) then the algorithms used can not fail.
I always ignored the return types (wondering who uses them) until today I saw this in glibc-2.11 (copied exactly from the source file) and everything became much more clear:
wchar_t *
wcsdup (s)
const wchar_t *s;
{
size_t len = (__wcslen (s) + 1) * sizeof (wchar_t);
void *new = malloc (len);
if (new == NULL)
return NULL;
return (wchar_t *) memcpy (new, (void *) s, len);
}
It makes it easier to write less code ("chain" it?) I guess.
Here's a pretty standard implementation of strcat from OpenBSD:
char *
strcat(char *s, const char *append)
{
char *save = s;
for (; *s; ++s);
while ((*s++ = *append++) != '\0');
return(save);
}
As long as the inputs passed to it are valid (i.e. append is properly terminated and s is large enough to concatenate it), this can't really fail - it's a simple memory manipulation. That memory is entirely under the control of the caller.
The return value here could be used to chain concatenations, for example:
strcat(strcat(s, t1), t2);
Although this is hardly efficient...
I have the following C code fragment and have to identify the error and suggest a way of writing it more safely:
char somestring[] = "Send money!\n";
char *copy;
copy = (char *) malloc(strlen(somestring));
strcpy(copy, somestring);
printf(copy);
So the error is that strlen ignores the trailing '\0' of a string and therefore it is not going to be allocated enough memory for the copy but I'm not sure what they're getting at about writing it more safely?
I could just use malloc(strlen(somestring)+1)) I assume but I'm thinking there must be a better way than that?
EDIT: OK, I've accepted an answer, I suspect that the strdup solution would not be expected from us as it's not part of ANSI C. It seems to be quite a subjective question so I'm not sure if what I've accepted is actually the best. Thanks anyway for all the answers.
I can't comment on the responses above, but in addition to checking the
return code and using strncpy, you should never do:
printf(string)
But use:
printf("%s", string);
ref: http://en.wikipedia.org/wiki/Format_string_attack
char somestring[] = "Send money!\n";
char *copy = strdup(something);
if (copy == NULL) {
// error
}
or just put this logic in a separate function xstrdup:
char * xstrdup(const char *src)
{
char *copy = strdup(src);
if (copy == NULL) {
abort();
}
return copy;
}
char somestring[] = "Send money!\n";
char *copy;
size_t copysize;
copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
bail("Oh noes!\n");
strncpy(copy, somestring, copysize);
printf("%s", copy);
Noted differences above:
Result of malloc() must be checked!
Compute and store the memory size!
Use strncpy() because strcpy() is naughty. In this contrived example it won't hurt, but don't get into the habit of using it.
EDIT:
To those thinking I should be using strdup()... that only works if you take the very narrowest view of the question. That's not only silly, it's overlooking an even better answer:
char somestring[] = "Send money!\n";
char *copy = somestring;
printf(copy);
If you're going to be obtuse, at least be good at it.
strlen + 1, for the \0 terminator
malloc may fail; always check malloc return value
Ick... use strdup() like everyone else said and write it yourself if you have to. Since you have time to think about this now... check out the 25 Most Dangerous Programming Errors at Mitre, then consider why the phrase printf(copy) should never appear in code. That is right up there with malloc(strlen(str)) in terms of utter badness not to mention the headache of tracking down why it causes lots of grief when copy is something like "%s%n"...
I would comment to previous solutions but I do not have enough rep.
Using strncpy here is as wrong as using strcpy(As there is absolutely no risk of overflow). There is a function called memcpy in < string.h > and it is meant exactly for this. It is not only significantly faster, but also the correct function to use to copy strings of known length in standard C.
From the accepted answer:
char somestring[] = "Send money!\n";
char *copy;
size_t copysize;
copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
bail("Oh noes!\n");
memcpy(copy, somestring, copysize); /* You don't use str* functions for this! */
printf("%s", copy);
to add more to Adrian McCarthy's ways to make safer code,
Use a static code analyzer, they are very good at finding this kind of errors
Ways to make the code safer (and more correct).
Don't make an unnecessary copy. From the example, there's no apparent requirement that you actually need to copy somestring. You can output it directly.
If you have to make a copy of a string, write a function to do it (or use strdup if you have it). Then you only have to get it right in one place.
Whenever possible, initialize the pointer to the copy immediately when you declare it.
Remember to allocate space for the null terminator.
Remember to check the return value from malloc.
Remember to free the malloc'ed memory.
Don't call printf with an untrusted format string. Use printf("%s", copy) or puts(copy).
Use an object-oriented language with a string class or any language with built-in string support to avoid most of these problems.
The best way to write it more safely, if one were to be truly interested in such a thing, would be to write it in Ada.
somestring : constant string := "Send money!";
declare
copy : constant string := somestring;
begin
put_line (somestring);
end;
Same result, so what are the differences?
The whole thing is done on the stack
(no pointers). Deallocation is
automatic and safe.
Everything is automaticly range-checked so
there's no chance of buffer-overflow
exploits
Both strings are constants,
so there's no chance of screwing up
and modifying them.
It will probably be way faster than the C, not only because of the lack of dynamic allocation, but because there isn't that extra scan through the string required by strlen().
Note that in Ada "string" is not some special dynamic construct. It's the built-in array of characters. However, Ada arrays can be sized at declaration by the array you assign into them.
The safer way would be to use strncpy instead of strcpy. That function takes a third argument: the length of the string to copy. This solution doesn't stretch beyond ANSI C, so this will work under all environments (whereas other methods may only work under POSIX-compliant systems).
char somestring[] = "Send money!\n";
char *copy;
copy = (char *) malloc(strlen(somestring));
strncpy(copy, somestring, strlen(somestring));
printf(copy);
I have a function that accepts a char* as one of its parameters. I need to manipulate it, but leave the original char* intact. Essentially, I want to create a working copy of this char*. It seems like this should be easy, but I am really struggling.
My first (naive) attempt was to create another char* and set it equal to the original:
char* linkCopy = link;
This doesn't work, of course, because all I did was cause them to point to the same place.
Should I use strncpy to accomplish this?
I have tried the following, but it causes a crash:
char linkCopy[sizeof(link)] = strncpy(linkCopy, link, sizeof(link));
Am I missing something obvious...?
EDIT: My apologies, I was trying to simplify the examples, but I left some of the longer variable names in the second example. Fixed.
The sizeof will give you the size of the pointer. Which is often 4 or 8 depending on your processor/compiler, but not the size of the string pointed to. You can use strlen and strcpy:
// +1 because of '\0' at the end
char * copy = malloc(strlen(original) + 1);
strcpy(copy, original);
...
free(copy); // at the end, free it again.
I've seen some answers propose use of strdup, but that's a posix function, and not part of C.
You might want to take a look at the strdup (man strdup) function:
char *linkCopy = strdup(link);
/* Do some work here */
free(linkCopy);
Edit: And since you need it to be standard C, do as others have pointed out:
char *linkCopy = malloc(strlen(link) + 1);
/* Note that strncpy is unnecessary here since you know both the size
* of the source and destination buffers
*/
strcpy(linkCopy, link);
/* Do some work */
free(linkCopy);
Since strdup() is not in ANSI/ISO standard C, if it's not available in your compiler's runtime, go ahead and use this:
/*
** Portable, public domain strdup() originally by Bob Stout
*/
#include <stdlib.h>
#include <string.h>
char* strdup(const char* str)
{
char* newstr = (char*) malloc( strlen( str) + 1);
if (newstr) {
strcpy( newstr, str);
}
return newstr;
}
Use strdup, or strndup if you know the size (more secure).
Like:
char* new_char = strdup(original);
... manipulate it ...
free(new_char)
ps.: Not a C standard
Some answers, including the accepted one are a bit off. You do not strcpy a string you have just strlen'd. strcpy should not be used at all in modern programs.
The correct thing to do is a memcpy.
EDIT: memcpy is very likely to be faster in any architecture, strcpy can only possibly perform better for very short strings and should be avoided for security reasons even if they are not relevant in this case.
You are on the right track, you need to use strcpy/strncpy to make copies of strings. Simply assigning them just makes an "alias" of it, a different name that points to the same thing.
Your main problem in your second attempt is that you can't assign to an array that way. The second problem is you seem to have come up with some new names in the function call that I can't tell where they came from.
What you want is:
char linkCopy[sizeof(link)];
strncpy(linkCopy, chLastLink, sizeof(link));
but be careful, sizeof does not always work the way you want it to on strings. Use strlen, or use strdup.
Like sean.bright said strdup() is the easiest way to deal with the copy. But strdup() while widely available is not std C. This method also keeps the copied string in the heap.
char *linkCopy = strdup(link);
/* Do some work here */
free(linkCopy);
If you are committed to using a stack allocated string and strncpy() you need some changes. You wrote:
char linkCopy[sizeof(link)]
That creates a char array (aka string) on the stack that is the size of a pointer (probably 4 bytes). Your third parameter to strncpy() has the same problem. You probably want to write:
char linkCopy[strlen(link)+1];
strncpy(linkCopy,link,strlen(link)+1);
You don't say whether you can use C++ instead of C, but if you can use C++ and the STL it's even easier:
std::string newString( original );
Use newString as you would have used the C-style copy above, its semantics are identical. You don't need to free() it, it is a stack object and will be disposed of automatically.