Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I try to use strcpy; is it a good way to do so?
char *stringvar;
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string");
stringvar[strlen("mi string")] = '\0';
What do you think?
There is exactly one bug in it: You don't check for malloc-failure.
Aside from that, it's repetitive and error-prone.
And overwriting the terminator with the terminator is useless.
Also, the repeated recalculation of the string-length is expensive.
Anyway, as you already have to determine the length, prefer memcpy() over strcpy().
What you should do is extracting it into a function, let's call it strdup() (that is the name POSIX and the next C standard give it):
char* strdup(const char* s) {
size_t n = strlen(s) + 1;
char* r = malloc(n);
if (r)
memcpy(r, s, n);
return r;
}
char* stringvar = strdup("mi string");
if (!stringvar)
handle_error();
You don't need the last line
stringvar[strlen("mi string")] = '\0';
strcpy takes care of that for you.
In real code you absolutely must check malloc's return value to make sure it's not NULL.
Other than that your code is fine. In particular, you've got the vital + 1 in the call to malloc. strlen gives you the length of the string not including the terminating '\0' character, but strcpy is going to add it, so you absolutely need to allocate space for it.
The problem with strcpy -- the fatal problem, some people say -- is that at the moment you call strcpy, you have no way of telling strcpy how big the destination array is. It's your responsibility to make the array big enough, and avoid overflow. strcpy is unable, by itself, to prevent buffer overflow -- and of course if the destination does overflow, that's a big problem.
So then the question is, how can you ensure -- absolutely ensure -- that all the calls to strcpy in all the code you write are correct? And how can you ensure that later, someone modifying your program won't accidentally mess things up?
Basically, if you use strcpy at all, you want to arrange that two things are right next to each other:
the code that arranges that the pointer variable points to enough space for the string you're about to copy into it, and
the actual call to strcpy that copies the string into that pointer.
So your code
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string");
comes pretty close to that ideal.
I know your code is only an example, but it does let us explore the concern, what if later, someone modifying your program accidentally messes things up? What if someone changes it to
stringvar = malloc(strlen("mi string") + 1);
strcpy(stringvar, "mi string asombroso");
Obviously we've got a problem. So to make absolutely sure that there's room for the string we're copying, it's even better, I think, if the string we're copying is in a variable, so it's patently obvious that the string we're copying is the same string we allocated space for.
So here's my improved version of your code:
char *inputstring = "mi string";
char *stringvar = malloc(strlen(inputstring) + 1);
if(stringvar == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
strcpy(stringvar, inputstring);
(Unfortunately, the check for a NULL return from malloc gets in the way of the goal of having the strcpy call right next to the malloc call.)
Basically your code is an implementation of the C library function strdup, which takes a string you give it and returns a copy in malloc'ed memory.
One more thing. You were worried about the + 1 in the all to malloc, and as I said, it's correct. A pretty common error is
stringvar = malloc(strlen(inputstring));
strcpy(stringvar, inputstring);
This fails to allocate space for the \0, so when strcpy adds the \0 it overflows the allocated space, so it's a problem.
And with that said, make sure you don't accidentally write
stringvar = malloc(strlen("mi string" + 1));
Do you see the error? This is a surprisingly easy mistake to make, but obviously it doesn't do what you want it to do.
There are some issues with the code posted:
you do not check if malloc() succeeded: if malloc() fails and returns NULL, passing this null pointer to strcpy has undefined behavior.
the last statement stringvar[strlen("mi string")] = '\0'; is useless: strcpy does copy the null terminator at the end of the source string, making the destination array a proper C string.
Here is a corrected version:
#include <stdlib.h>
#include <string.h>
...
char *stringvar;
if ((stringvar = malloc(strlen("mi string") + 1)) != NULL)
strcpy(stringvar, "mi string");
Note that is would be slightly better to store the allocation size and not use strcpy:
char *stringvar;
size_t size = strlen("mi string") + 1;
if ((stringvar = malloc(size)) != NULL)
memcpy(stringvar, "mi string", size);
Indeed it would be even simpler and safer to use strdup(), available on POSIX compliant systems, that performs exactly the above steps:
char *stringvar = strdup("mi string");
Related
I wonder if there is a way to initialize a string array to a value I decide on during memory allocation, so it won't contain any garbage and the null character will be placed at the correct place. I know that using calloc the memory allocated is initialized to all zeros, but in this case involving strings it doesn't help.
I practice using pointers and allocation memory in C.
There is an exercise in which I wrote a function for copying a string to another string - In main(), I allocate memory using malloc for both strings based on the strings lengths the user provides, and then the user enters the first string.
At this point I send the pointer of the first string and second string (uninitialized) as parameters to strCopy(char* str1, char* str2). Inside that function I also use another basic function I wrote, to calculate the length of a string. but as you may guess, since the second string is full of garbage, it's length calculation inside the function is messed up.
void strCopy(char* str1, char* str2)
{
int str1len = str_len(str1); // basic length calculating function
int str2len = str_len(str2);
int i;
for (i = 0; i < str2len; i++)
{
str2[i] = str1[i];
}
str2[i] = '\0';
if (str2len < str1len)
printf("There wasn't enought space to copy the entire string. %s was
copied.\n", str2);
else
printf("The string %s has been copied.\n", str2);
}
Right now it works fine when initializing str2 in a loop in main(), but I am interested in other possible solutions.
Thank you very much for any help!
No, there is not. You have to manually initialize it.
If you want to copy a string while allocating memory, you can use strdup. Note that this is a POSIX function, which means this will only work on POSIX-compliant operating systems, Windows, and any other OSs that implement it.
Well, for this particular situation you can use memcpy. A simple way could be like this in your code instead of the for loop:
memcpy(str2, str1, str2len);
But your code is seriously flawed. I don't know how you have implemented str_len but there is absolutely no way (if you're not using non-standard, non-portable, dirty hacks) to get the size of the block that a pointer is pointing to.
In C I have a path in one of my strings
/home/frankv/
I now want to add the name of files that are contained in this folder - e.g. file1.txt file123.txt etc.
Having declared my variable either like this
char pathToFile[strlen("/home/frankv/")+1]
or
char *pathToFile = malloc(strlen("/home/frankv/")+1)
My problem is that I cannot simply add more characters because it would cause a buffer overflow. Also, what do I do in case I do not know how long the filenames will be?
I've really gotten used to PHP lazy $string1.$string2 .. What is the easiest way to do this in C?
If you've allocated a buffer with malloc(), you can use realloc() to expand it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *buf;
const char s1[] = "hello";
const char s2[] = ", world";
buf = malloc(sizeof s1);
strcpy(buf, s1);
buf = realloc(buf, sizeof s1 + sizeof s2 - 1);
strcat(buf, s2);
puts(buf);
return 0;
}
NOTE: I have omitted error checking. You shouldn't. Always check whether malloc() returns a null pointer; if it does, take some corrective action, even if it's just terminating the program. Likewise for realloc(). And if you want to be able to recover from a realloc() failure, store the result in a temporary so you don't clobber your original pointer.
Use std::string, if possible. Else, reallocate another block of memory and use strcpy and strcat.
You have a couple options, but, if you want to do this dynamically using no additional libraries, realloc() is the stdlib function you're looking for:
char *pathToFile = malloc(strlen("/home/frankv/")+1);
char *string_to_add = "filename.txt";
char *p = realloc(pathToFile, strlen(pathToFile) + strlen(string_to_add) + 1);
if (!p) abort();
pathToFile = p;
strcat(p, string_to_add);
Note: you should always assign the result of realloc to a new pointer first, as realloc() returns NULL on failure. If you assign to the original pointer, you are begging for a memory leak.
If you're going to be doing much string manipulation, though, you may want to consider using a string library. Two I've found useful are bstring and ustr.
In case you can use C++, use the std::string. In case you must to use pure C, use what's call doubling - i.e. when out of space in the string - double the memory and copy the string into the new memory. And you'll have to use the second syntax:
char *pathToFile = malloc(strlen("/home/frankv/")+1);
You have chosen the wrong language for manipulating strings!
The easy and conventional way out is to do something like:
#define MAX_PATH 260
char pathToFile[MAX_PATH+1] = "/home/frankv/";
strcat(pathToFile, "wibble/");
Of course, this is error prone - if the resulting string exceeds MAX_PATH characters, anything can happen, and it is this sort of programming which is the route many trojans and worms use to penetrate security (by corrupting memory in a carefully defined way). Hence my deliberate choice of 260 for MAX_PATH, which is what it used to be in Windows - you can still make Windows Explorer do strange things to your files with paths over 260 characters, possibly because of code like this!
strncat may be a small help - you can at least tell it the maximum size of the destination, and it won't copy beyond that.
To do it robustly you need a string library which does variable length strings correctly. But I don't know if there is such a thing for C (C++ is a different matter, of course).
I got a problem today. It had a method and I need to find the problem in that function. The objective of the function is to append new line to the string that is passed. Following is the code
char* appendNewLine(char* str){
int len = strlen(str);
char buffer[1024];
strcpy(buffer, str);
buffer[len] = '\n';
return buffer;
}
I had identified the problem with this method. Its kind of straight forward. The method is having a potential of having array's index out of range. That is not my doubt. In java, I use '\n' for newline. (I am basically a Java programmer, its been many years I've worked in C). But I vaguely remember '\n' is to denote termination for a string in C. Is that also a problem with this program?
Please advise.
Theres quite a few problems in this code.
strlen and not strlent, unless you have an odd library function there.
You're defining a static buffer on the stack. This is a potential bug (and a security one as well) since a line later, you're copying the string to it without checking for length.
Possible solutions to that can either be allocating the memory on the heap (with a combination of strlen and malloc), or using strncpy and accepting the cut off of the string.
Appending '\n' indeed solves the problem of adding a new line, but this creates a further bug in that the string is currently not null terminated.
Solution: Append '\n' and '\0' to null terminate the new string.
As others have mentioned, you're returning a pointer to a local variable, this is a severe bug and makes the return value corrupt within a short time.
To expand your understanding of these problems, please look up what C-style strings are, potentially from here. Also, teach yourself the difference between variables allocated on the stack and variables allocated on the heap.
EDITed: AndreyT is correct, the definition of length is valid
No, a '\n' is a new-line in c, just like in Java (Java grabbed that from C). You've identified one problem: if the input string is longer than your buffer, you'll write past the end of buffer. Worse, your return buffer; returns the address of memory that's local to the function and will cease to exist when the function exits.
First this is a function, not a program.
This function returns a pointer to a local variable. Such variables are typically created on the stack are no more available when the function exits.
Another problem is if the passed is longer than 1024 chars ; in this case, strcpy() will write past the buffer.
One solution is to allocate a new buffer in dynamic memory and to return a pointer to that buffer. The size of the buffer shall be len +2 (all chars + newline + \0 string terminator), but someone will have to free this buffer (and possibly the initial buffer as well).
strlent() does not exist, it should be strlen() but I suppose this is just a typo.
This function returns buffer, which is a local variable on the stack. As soon as the function returns the memory for buffer can be reused for another purpose.
You need to allocate memory using malloc or similar if you intend to return it from a function.
There are other issues with the code as well - you do not ensure that buffer is large enough to contain the string you are trying to copy to it and you do not make sure the string ends with a null-terminator.
C strings end with '\0'.
And as your objective is to append newLine, following would do fine (will save you copying the entire string into a buffer):
char* appendNewLine(char* str){
while(*str != '\0') str++; //assumming the string ended with '\0'
*str++ = '\n'; //assign and increment the pointer
*str = '\0';
return str; //optional, you could also send 0 or 1, whether
//it was successful or not
}
EDIT :
String should have space to accommodate the extra '\n' and since the OBJECTIVE itself is to append, which means adding to the original, its safe to assume string has space for atleast one more char!!
But, if you dont want to assume anything,char* appendNewLine(char* str){
int length = strlen(str);
char *newStr = (char *)malloc(1 + length);
*(newStr + length) = '\n';
*(newStr + length + 1) = '\0';
return newStr;
}
Add a null after the newline:
buffer[len] = '\n';
buffer[len + 1] = 0;
The terminator for a string in C is '\0' not '\n'. It stands only for newline.
There are at least two problems with your program.
Firstly, you seem to want to build a string, but you never zero-terminate it.
Secondly, you function returns a pointer to locally declared buffer. Doing this makes no sense.
There are several issues with the code:
It can buffer overflow since buffer is hardcoded to allocate only 1024 characters. Worse yet, the buffer is not even allocated in the heap.
The newline "character" is actually operating system-dependent. Strictly speaking, it's only \n in Unix etc. In Windows, and in strict internet protocol, it's \r\n, for example.
The string returned by the function is not null-terminated. This is most likely not what you'd want.
Also, taking into account your background in Java, here are some things that you should consider:
Since you're working with C char* and not (immutable) Java strings, maybe you could append the newline in-place?
Array access is no longer checked at run time, so you have to be VERY careful about going out of bounds. Make sure that all buffers are of appropriate size.
The language does not come with standard automatic garbage collection, so if you do choose to allocate new buffers for string manipulation, make sure that you manage your memory properly and aren't leaking everywhere.
char* appendNewLine(char* str){
int len = strlen(str);
char buffer[1024];
strcpy(buffer, str);
buffer[len] = '\n';
return buffer;
}
Another important issue is the buffer variable; its supposed to be a local stack variable. As soon as the function returns it is being destroyed from stack. And returning pointer to the buffer probably means you are going to crash your process if you try to write at the returned pointer (address of buffer that's address on stack).
Use malloc instead
I am ignoring the return of a local, as others have eloquently addressed that.
int len = strlen(str);
char buffer[1024];
...
buffer[len] = '\n';
If strlen(str) > 1024, then this sequence would write beyond the bounds of the declared buffer. Also as noted, this would (probably) not be null terminated.
To safely append a new line if possble,
char buffer[1024];
strncpy(buffer, str, 1024); // truncate string if it is too long
int len = strlen(buffer);
if (len < 1022) {
buffer[len] = '\n';
buffer[len + 1] = '\0';
}
Note: If the string is too long, This leave the truncated string WITHOUT the new line.
C string must end with '\0'.
buffer[len+1] = '\0';
You should dynamically allocate the buffer as a pointer to char of size len:
char *buffer = malloc(len*sizeof(char));
Maybe \n should be \r\n. Return + new line. It's what i always use and works for me.
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.