copy of a string pointer - c

I have a function that has input and pointer to an array of char in C. in that function I am manipulating the main string, however I want to make a backup copy in another variable before I use it. I want to put it in char backup[2000], so if the pointer changes the backup won't change.
How can I do that?

void function (const char *string)
{
char *stringcopy = malloc (1 + strlen (string));
if (stringcopy)
strcpy (stringcopy, string);
else fprintf (stderr, "malloc failure!"):
...
do whatever needs to be done with `stringcopy`
}

To duplicate strings in C there is a library function called strdup made for that:
The memory allocated by strdup must be freed after usage using free.
strdup provides the memory allocation and string copy operation in one step. Using an char array can become problematic if at some point in time the string to copy happens to be larger than the array's size.

Your friends are the following functions
malloc
memset
calloc
memcpy
strcpy
strdup
strncpy
But best of all, greatest friend is man :)

Use strncpy().
void myfunc(char* inputstr)
{
char backup[2000];
strncpy(backup, inputstr, 1999);
backup[1999] = '\0';
}
Copying 1999 characters to the 2000 character array leaves the last character for the null terminator.

You can use strcpy to make a copy of your char array (string) before you start modifying.

Use memcpy to create the backup.
char backup[2000];
char original[2000];
sprintf(original, "lovely data here");
memcpy(backup, original, 2000);
char* orig_ptr = original;

strcpy reference.
strcpy( backup, source );
Note from link.
To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.

Related

strcpy after strtok segmentfault in C

char test[10]="ab cd";
char* save=NULL;
save = strtok(test," ");
printf("%s\n",save);
result : ab
First, above code works very well.
Next, I tryed to excute this code. but, segmentfault occurs.
char test[10]="ab cd";
char* save=NULL;
char* cpy=NULL;
save = strtok(test," ");
strcpy(cpy,save);
printf("%s\n",cpy);
I know strtok() returns read-only *char type.
but, i guess, 'save' is used only copied object.
it is not change. why strcpy() makes segmentfault error by get 'save' as parameter?
cpy is explicitly NULL when you copy into the location it's pointing to. That's guaranteed to give you a memory write error of some kind.
I suggest you initialize cpy to point to some memory that's actually available, e.g.:
char temp[100];
char test[10]="ab cd";
char* save=NULL;
char* cpy=temp; // Set cpy to point to temp buffer
save = strtok(test," ");
strcpy(cpy,save);
printf("%s\n",cpy);
It's not strtok() that's causing the problem, it's the strcpy() into address 0.
Your char *cpy is not referencing any allocated memory. (You initialized it to NULL. So when you call strcpy(cpy,save), you are writing to a NULL-pointer.
You might want to allocate memory first:
cpy = malloc(strlen(save)+1);
strcyp(cpy,save);
In strcpy case you have to first allocate memory for "cpy" so that "save" can be copied to "cpy". Here "save" is working fine because strtok only return pointer on success...That's why you don't need to allocate memory for "save".And you are passing an address by save so it's fine..So overall first allocate memory for "cpy" so that strcpy can copy "save" into "cpy".
Use strdup
save = strtok(test," ");
cpy = strdup(save);
printf("%s\n",cpy);
free(cpy);
Don't forget to free the memory when you're done with it.
Also read this
As provided earlier, strcpy() like most string routines will segfault if passed a NULL argument. This applies to both the src and dest args (at least in older versions of glibc), which makes it impossible to do simple things like:
strcpy(dest, strtok(NULL, “ “));
strcpy(dest, getenv(“NOTHNG”);
Either strtok() or getenv() could return a NULl, which is passed to strcpy() causing a segfault. I didn’t want to put a lot of NULL checking into my code, like:
if (getenv(“NOTHING”) != NULL)
*dest = ‘\0’;
else
strcpy(dest, getenv(“NOTHING”));
So, I created a strcpy_w() wrapper that treats a NULL src argument the same as if *src is ‘\0’. I did the same for other string functions, also checking for buffer overflows. Then, I just had to add the following to always use the wrapper:
#define strcpy(x, y) strcpy_w(x, y)
Or I could call strcpy_w(dest, getenv(“NOTHING”)) instead.

In C - function get char pointer and add characters to it

I am trying to think how to write a function that get char* and return a pointer to the same char but after added to his end few constant characters.
char* addExtension(char* FileName)
{
}
That's just what the standard library function strcat() (for "string concatenate") does, I think. You should look into using it.
Also beware of the dangers of buffer overrun, a function such as this (and strcat(), for that matter) is inherently unsafe since it doesn't include information about available space.
You really can't do that, not with arbitrary strings anyway.
Strings can be:
Constants (like the literal "hello world"). Those can't be modified
Char arrays (like char thingie[10]). They have fixed amout of space - if you
run out of it, you get the very friendly Segmentation fault or worse.
malloc'd pointers - they have fixed amount of space, too, and need to be freed.
You can copy the string and return a new one, but that can result in memory leaks
if you don't take care of the old one. Example
char *copycat(char *first, char *second) {
char *result = malloc(strlen(first)+strlen(second)+1);
strcpy(result, first);
strcpy(result+strlen(first), second);
return result;
}

Assign string to element in structure in C

I have this structure:
typedef struct SM_DB
{
LIST_TYPE link;
char name[SM_NAME_SIZE];
} SM_DB_TYPE;
And I would like to assign a string to its 'name'. I am doing so like this:
SM_DB_TYPE one;
one.name = "Alpha";
However, after compiling I get an error: "error C2106: '=' : left operand must be l-value". I am hoping this is fairly obvious. Does anyone know what I am doing wrong?
Thanks
Assuming SM_NAME_SIZE is large enough you could just use strcpy like so:
strcpy(one.name, "Alpha");
Just make sure your destination has enough space to hold the string before doing strcpy your you will get a buffer overflow.
If you want to play it safe you could do
if(!(one.name = malloc(strlen("Alpha") + 1))) //+1 is to make room for the NULL char that terminates C strings
{
//allocation failed
}
strcpy(one.name, "Alpha"); //note that '\0' is not included with Alpha, it is handled by strcpy
//do whatever with one.name
free(one.name) //release space previously allocated
Make sure you free one.name if using malloc so that you don't waste memory.
You can assign value to string only while declaring it. You can not assign it later by using =.
You have to use strcpy() function.
Use strcpy or strncpy to assign strings in C.
C does not have a built in string type. You must use an array of characters to hold the string.
Since C also does not allow the assignment of one array to another, you have to use the various functions in the Standard C Library to copy array elements from one array to another or you have to write a loop to do it yourself. Using the Standard C Library functions is much preferred though there are sometimes reasons to write your own loop.
For standard ANSI type strings used with the char type there are a large number of functions most of which begin with str such as functions to copy or compare strings strcpy(), strcmp(). There are also another set which you specify the maximum number of characters to copy or compare such as strncpy() or strncmp().
A string in C is an array of characters that is terminated by a binary zero character. So if you use a constant string such as "Constant" this will create an array of characters that has one element per character plus an additional element for the zero terminator.
This means that when sizing char arrays you must also remember to add one more extra array element to hold the zero terminator.
The strncpy() function will copy one char array to another up to either the maximum number of characters specified or when the zero terminator is found. If the maximum number of characters is reached then the destination array will not be terminated by a zero terminator so this is something to watch out for.
char one[10];
char two[20];
strncpy (one, "1234567", 10); // copy constant to the char buffer max of 10 chars
one[9] = 0; // make sure the string is zero terminated, it will be this is demo
strcpy (two, one);
strcat (two, " suffix"); // add some more text to the end
There are also functions to work with wide characters used with UNICODE.
Use:
strcpy(one.name, "Alpha"); //Removed null byte (Read first comment by shf301)
Alternative:
typedef struct SM_DB
{
LIST_TYPE link;
char* name;
} SM_DB_TYPE;
SM_DB_TYPE one;
one.name = malloc(sizeof(char) * (strlen("Alpha") + 1); //Allocate memory
if (!one.name) {
/* Error handling */
} else {
strcpy(one.name, "Alpha");
}

Make a copy of a char*

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.

strdup() - what does it do in C?

What is the purpose of the strdup() function in C?
Exactly what it sounds like, assuming you're used to the abbreviated way in which C and UNIX assigns words, it duplicates strings :-)
Keeping in mind it's actually not part of the current (C17) ISO C standard itself(a) (it's a POSIX thing), it's effectively doing the same as the following code:
char *strdup(const char *src) {
char *dst = malloc(strlen (src) + 1); // Space for length plus nul
if (dst == NULL) return NULL; // No memory
strcpy(dst, src); // Copy the characters
return dst; // Return the new string
}
In other words:
It tries to allocate enough memory to hold the old string (plus a '\0' character to mark the end of the string).
If the allocation failed, it sets errno to ENOMEM and returns NULL immediately. Setting of errno to ENOMEM is something malloc does in POSIX so we don't need to explicitly do it in our strdup. If you're not POSIX compliant, ISO C doesn't actually mandate the existence of ENOMEM so I haven't included that here(b).
Otherwise the allocation worked so we copy the old string to the new string(c) and return the new address (which the caller is responsible for freeing at some point).
Keep in mind that's the conceptual definition. Any library writer worth their salary may have provided heavily optimised code targeting the particular processor being used.
One other thing to keep in mind, it looks like this is currently slated to be in the C2x iteration of the standard, along with strndup, as per draft N2912 of the document.
(a) However, functions starting with str and a lower case letter are reserved by the standard for future directions. From C11 7.1.3 Reserved identifiers:
Each header declares or defines all identifiers listed in its associated sub-clause, and optionally declares or defines identifiers listed in its associated future library directions sub-clause.*
The future directions for string.h can be found in C11 7.31.13 String handling <string.h>:
Function names that begin with str, mem, or wcs and a lowercase letter may be added to the declarations in the <string.h> header.
So you should probably call it something else if you want to be safe.
(b) The change would basically be replacing if (d == NULL) return NULL; with:
if (d == NULL) {
errno = ENOMEM;
return NULL;
}
(c) Note that I use strcpy for that since that clearly shows the intent. In some implementations, it may be faster (since you already know the length) to use memcpy, as they may allow for transferring the data in larger chunks, or in parallel. Or it may not :-) Optimisation mantra #1: "measure, don't guess".
In any case, should you decide to go that route, you would do something like:
char *strdup(const char *src) {
size_t len = strlen(src) + 1; // String plus '\0'
char *dst = malloc(len); // Allocate space
if (dst == NULL) return NULL; // No memory
memcpy (dst, src, len); // Copy the block
return dst; // Return the new string
}
char * strdup(const char * s)
{
size_t len = 1+strlen(s);
char *p = malloc(len);
return p ? memcpy(p, s, len) : NULL;
}
Maybe the code is a bit faster than with strcpy() as the \0 char doesn't need to be searched again (It already was with strlen()).
No point repeating the other answers, but please note that strdup() can do anything it wants from a C perspective, since it is not part of any C standard. It is however defined by POSIX.1-2001.
From strdup man:
The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1. The returned pointer can be passed to free(). A null pointer is returned if the new string cannot be created.
strdup() does dynamic memory allocation for the character array including the end character '\0' and returns the address of the heap memory:
char *strdup (const char *s)
{
char *p = malloc (strlen (s) + 1); // allocate memory
if (p != NULL)
strcpy (p,s); // copy string
return p; // return the memory
}
So, what it does is give us another string identical to the string given by its argument, without requiring us to allocate memory. But we still need to free it, later.
strdup and strndup are defined in POSIX compliant systems as:
char *strdup(const char *str);
char *strndup(const char *str, size_t len);
The strdup() function allocates sufficient memory for a copy of the
string str, does the copy, and returns a pointer to it.
The pointer may subsequently be used as an argument to the function free.
If insufficient memory is available, NULL is returned and errno is set to
ENOMEM.
The strndup() function copies at most len characters from the string str always null terminating the copied string.
It makes a duplicate copy of the string passed in by running a malloc and strcpy of the string passed in. The malloc'ed buffer is returned to the caller, hence the need to run free on the return value.
The most valuable thing it does is give you another string identical to the first, without requiring you to allocate memory (location and size) yourself. But, as noted, you still need to free it (but which doesn't require a quantity calculation, either.)
The statement:
strcpy(ptr2, ptr1);
is equivalent to (other than the fact this changes the pointers):
while(*ptr2++ = *ptr1++);
Whereas:
ptr2 = strdup(ptr1);
is equivalent to:
ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);
So, if you want the string which you have copied to be used in another function (as it is created in heap section), you can use strdup, else strcpy is enough,
The strdup() function is a shorthand for string duplicate, it takes in a parameter as a string constant or a string literal and allocates just enough space for the string and writes the corresponding characters in the space allocated and finally returns the address of the allocated space to the calling routine.

Resources