How to memcpy() from argv[]? - c

I want to copy string from argv[0] but I don't know how to get the size of argv[0].
How to do this?
int main(int argc, char* argv[])
{
char str[20];
if(argc>0)
memcpy(str, argv[0], sizeof(argv[0]));
}

Since argv[0] is a string, use strlen.
#include <string.h>
size_t length = strlen (argv[0]) + 1;
memcpy (str, argv[0], length);
By the way, you could also use strcpy, which is more suitable for strings.
#include <string.h>
strcpy (str, argv[0]);
In every case, in order to make sure that your copy won't overflow, you should check whether the size of str is sufficient.
if (sizeof str >= length)
{
/* Do the copy. */
}
else
{
/* Report an error, or use dynamic allocation. */
}

You can use strdup() if your platform supports it. this makes your code more simple
int main(int argc, char* argv[])
{
char *str = NULL;
if(argc>0) {
str = strdup(argv[0]);
}
.......
// when the str became useless then free it
free(str);
........
}

You need to use strlen. If you were to use sizeof, then you would get the size of the char*.
To copy the string, you should use strcpy or just assign to another char*. Better yet, use strncpy in conjunction with a size (the size of the destination - 1) to prevent buffer overflows into str. The -1 is to account for the null-terminating character (\0). Don't forget about this character! The problem becomes if strlen returns 20. Then it will drop the \0. You should also read up on secure use of strcpy and you can read more about strncpy here.
OR, you can do this and it makes everything I said moot:
const char* arg1 = argv[0];
which would make strlen pointless in this case.

char* argv[] is an array of pointers (char*) so sizeof(argv[0]) is equal to sizeof(char*).
You could either use strlen:
memcpy(str, argv[0], strlen(argv[0]) + 1); // +1 because of '\0' at the end
or yet even better you could use strcpy:
strcpy(str, argv[0]);
but note that the length of the argv[0] might be greater than the size of your destination buffer (str) so you should either check the size of argv[0] before copying it.
You could also use strcnpy to copy only specified amount of characters, but in that case be very careful, because if there is no \0 in first 20 characters of argv[0], you'll have to terminate your string explicitly.

If your Cxx is >= C99
than you can do it in this way:
int main(int argc, char* argv[])
{
int len = (argc>0) ? strlen(argv[0]) : 0;
char str[len+1];
if (argc>0)
memcpy(str, argv[0], len+1);
}

I suggest to you to use pointer and allocate memory depending of the length of argv[0]:
int main(int argc, char* argv[])
{
char *str = NULL;
if(argc>0) {
int len = strlen(argv[0])
str = malloc((len+1) * sizeof(char))
memcpy(str, argv[0], (len+1));
}
.......
// when the str became useless then free it
free(str);
........
}

To summarise, because there's a lot of confusion and bad advice here:
The answer to your question in the narrowest sense is that you can find out the length of strings using strlen (sizeof returns the size of the data type in bytes, which for strings in char*, which (on a typical modern machine) will be either 4 (on 32-bit systems) or 8 (on 64-bit systems) regardless of the length of the string), but...
Make sure this is something you need to be doing in the first place. If you don't intend to change the string, there's no reason to copy it. If you do intend to change it, you only need to copy it if you also want to preserve the old value, because the argv strings are mutable (as per the standard).
If you either don't intend to change it or don't need the old value, but you still want another variable for some reason (readability, presumably), you should declare that variable as a pointer rather than an array and just assign to it:
char *str = argv[0];
If you're sure you do want to copy the string, you should not be using memcpy for this. You should be using strcpy, and you should be sure your new string is big enough to hold argv[0]. If you're using C99, you can do this easily:
char str[strlen(argv[0]) + 1];
strcpy(str, argv[0]);
If you're using an older standard, you will need to allocate memory dynamically:
char *str = malloc(strlen(argv[0]) + 1);
strcpy(str, argv[0]);
If you're on a POSIX system, you can shorten that by using strdup:
char *str = strdup(argv[0]);
If you're using malloc or strdup, remember that you need to free your memory manually when you're done with it.
(You don't need to check if argc > 0 in any case, by the way; the standard guarantees that argv[0] is either the program name or a zero-length string (that is, argv[0][0] is '\0').)
If you can't get away from using a fixed-length buffer, you can use strncpy if you remember to nul-terminate the resulting string manually and it's acceptable that your string is truncated if it is longer than the buffer:
char str[20];
strncpy(str, argv[0], 20); /* or 19, it doesn't matter. */
str[19] = '\0';
I think that's everything.

There is such a flood of bad advice here, I have no idea why, this question is not complicated rocket science, but rather beginner level programming.
You check that there is an argument in argv[0], but formally there will always be at least one argument passed to main. The check against argc > 0 is to be regarded as defensive programming, but extra error checks are never bad.
You need to check against buffer overflows before copying the contents of an unknown buffer.
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
if(argc == 0)
{
// unexpected error
}
size_t len = strlen(argv[0]);
char* str = malloc(len * sizeof(char) + 1);
if(str == NULL)
{
// no memory, error
}
strcpy(str, argv[0], len);
...
free(str);
}
And that's it.
strdup is bad advice because it isn't C standard and therefore not portable. It is also a completely superfluous function.
strncpy is bad advice, it was never intended as a secure version of strcpy. It is an old legacy function for handling records in dinosaur unix systems. It is much more dangerous than strcpy because it is easy to forget the null termination. There is never a reason to use strncpy in a modern C program. For some reason unknown, there is a lot of programmers who have been brainwashed into using strncpy as a guard against buffer overflows. Don't do this, the correct way is to ensure that the buffer is large enough before using strcpy/memcpy.

Related

Why is this use of strcpy considered bad?

I've spotted the following piece of C code, marked as BAD (aka buffer overflow bad).
The problem is I don't quite get why? The input string length is captured before the allocation etc.
char *my_strdup(const char *s)
{
size_t len = strlen(s) + 1;
char *c = malloc(len);
if (c) {
strcpy(c, s); // BAD
}
return c;
}
Update from comments:
the 'BAD' marker is not precise, the code is not bad, not efficient yes, risky (below) yes,
why risky? +1 after the strlen() call is required to safely allocate the space on heap that also will keep the string terminator ('\0')
There is no bug in your sample function.
However, to make it obvious to future readers (both human and mechanical) that there is no bug, you should replace the strcpy call with a memcpy:
char *my_strdup(const char *s)
{
size_t len = strlen(s) + 1;
char *c = malloc(len);
if (c) {
memcpy(c, s, len);
}
return c;
}
Either way, len bytes are allocated and len bytes are copied, but with memcpy that fact stands out much more clearly to the reader.
There's no problem with this code.
While it's possible that strcpy can cause undefined behavior if the destination buffer isn't large enough to hold the string in question, the buffer is allocated to be the correct size. This means there is no risk of overrunning the buffer.
You may see some guides recommend using strncpy instead, which allows you to specify the maximum number of characters to copy, but this has its own problems. If the source string is too long, only the specified number of characters will be copied, however this also means that the string isn't null terminated which requires the user to do so manually. For example:
char src[] = "test data";
char dest[5];
strncpy(dest, src, sizeof dest); // dest holds "test " with no null terminator
dest[sizeof(dest) - 1] = 0; // manually null terminate, dest holds "test"
I tend towards the use of strcpy if I know the source string will fit, otherwise I'll use strncpy and manually null-terminate.
I cannot see any problem with the code when it comes to the use of strcpy
But you should be aware that it requires s to be a valid C string. That is a reasonable requirement, but it should be specified.
If you want, you could put in a simple check for NULL, but I would say that it's ok to do without it. If you're about to make a copy of a "string" pointed to by a null pointer, then you probably should check either the argument or the result. But if you want, just add this as the first line:
if(!s) return NULL;
But as I said, it does not add much. It just makes it possible to change
if(!str) {
// Handle error
} else {
new_str = my_strdup(str);
}
to:
new_str = my_strdup(str);
if(!new_str) {
// Handle error
}
Not really a huge gain

Allocate memory to a specific "string"

I just started to learn memory management in C, and I didn't understand something. I want to allocate memory to a buffer that holds 12 bytes. which is the exact size of Hello World! without null terminator.
Then I want to append a string to the current string with strcat, and of course I cannot do that because I will get core dumped error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char mystr[12] = "Hello World!";
# allocate memory to mystr?
char *ptr = (char*) malloc(13 * sizeof(char));
strcat(mystr, "Hello");
return 0;
}
So, I don't know how can I allocate memory to the mystr variable if malloc doesn't take any other arguments except the target size.
I don't know how can I allocate memory to the mystr variable if malloc doesn't take any other arguments except the target size.
It is not possible to allocate extra memory to an array. Instead, what you want to do is allocate a new block of memory, copying the original string into the beginning of that memory (strcpy), then append the rest (strcat):
char *p = (char*) malloc((12 + 5 + 1) * sizeof(char));
strcpy(p, myptr);
strcat(p, "Hello");
12 for the first string, plus 5 for the second, plus one for the null-terminator.
Of course, since you know the final size, you could also simply allocate a big enough array instead of using malloc (and you can also use memcpy, too).
The problem should be that a string in C always end with a NULL character (also noted '\0'), so your string is actually 13 characters long. (That character is always automatically added with string literals and serves at telling where the string stops, because a string doesn't have a fixed length.)
So the strcat tries to read the string Hello world! followed by garbage (since the null-terminator is not included in the string).
P.S.: the error is not the core dumped but the Segmentation fault that precedes it, and this tells you that you are trying to change something in a segment you are not supposed to change (or execute/read something you are not supposed to -- this is a security feature).
Edit: after modifying the string mystr, you also need to change the length you allocate (in the malloc: use 13 * sizeof(char), or more simply here in this case sizeof(mystr)).
P.S. 2: also comments in C are started by //, not # (those are preprocessor directives).
you cant change the size of the array. mystr has to be also dynamically allocated.
int main(int argc, char const *argv[])
{
const char *ptr = "Hello World!";
const char *ptr2 = "hello";
char *mystr = malloc(strlen(ptr)+1);
strcpy(mystr, ptr);
mystr = realloc(mystr, strlen(mystr) + strlen(ptr2) + 1);
strcat(mystr, ptr2);
return 0;
}

How to read argv[1][1 - untill the end of the string] in C

I am trying to read argv[1] starting from the second character until the end of the string in argv[1] (ignoring the first character, which is a flag). How can I do this?
I tried some library functions and other ways such as storing it in a variable such as
char *variable = strncpy(argv[1][1], strlen(argv[1]))
but it didn't work.
You are running up against two fundamental misconceptions regarding variables and pointers in C.
Let's start with:
char *variable = strncpy(argv[1][1], strlen(argv[1]))
The biggest problem (aside from the improper use of strncpy) is you attempt to assign the return of strncpy to char *variable where char *variable is a pointer-to-char that is uninitialized and points to no valid storage. Your attempt to assign the return fails because the proper prototype for strncpy is:
char *strncpy(char *dest, const char *src, size_t n);
(note: the dest parameter. The destination must have adequate storage to accept n characters. **further note:** if there is nonull byte` among the first n bytes of src, the array of bytes placed in dest will not be a null-terminated string.)
Now either by cleverness or happy-circumstance using the strlen of the complete argv[1] to allocate storage for dest and copying from argv[1] + 1 does provide space for the null byte.
Your next misconception is using argv[1][1] in strncpy. argv[1][1] has type char, not char*. (though your could use &argv[1][1] to use the address of argv[1][1] -- but not as you have it above.
argv[1] is a pointer of type char *. Being a pointer-to-char, if you want to skip one char, you want to read from the address pointer + 1 (or argv[1] + 1 in this case). Now it may make things easier to understand if you declare a separate pointer, e.g. char *p = argv[1]; and then use p + 1, but it is the same thing.
Putting that together, it looks like you intended:
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv) {
if (argc < 2)
return 1;
size_t len = strlen (argv[1]);
char variable[len];
strcpy (variable, argv[1] + 1);
printf ("variable : %s\n", variable);
return 0;
}
Where with your example argument of +name, you would get:
Example Use/Output
$ ./bin/argv1plus1 +name
variable : name
For sake of completeness, if your compiler does not support use of a Variable Length Array (VLA) as used in char variable[len]; above, then your options are to declare variable as a fixed size array and validate that strlen(argv[1]) has no more characters than your fixed size, or, you simply allocate storage for variable dynamically by calling malloc (or calloc or realloc). A short example using malloc would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
if (argc < 2)
return 1;
size_t len = strlen (argv[1]);
char *variable = malloc (len); /* allocate a block of memory len chars long */
if (variable == NULL) { /* always validate malloc succeeded */
perror ("malloc failure");
exit (EXIT_FAILURE);
}
strcpy (variable, argv[1] + 1);
printf ("variable : %s\n", variable);
free (variable); /* don't forget to free the memory you allocate */
return 0;
}
(same example & output)
Look things over and let me know if you have further questions.

Copying a part of a string (substring) in C

I have a string:
char * someString;
If I want the first five letters of this string and want to set it to otherString, how would I do it?
#include <string.h>
...
char otherString[6]; // note 6, not 5, there's one there for the null terminator
...
strncpy(otherString, someString, 5);
otherString[5] = '\0'; // place the null terminator
Generalized:
char* subString (const char* input, int offset, int len, char* dest)
{
int input_len = strlen (input);
if (offset + len > input_len)
{
return NULL;
}
strncpy (dest, input + offset, len);
return dest;
}
char dest[80];
const char* source = "hello world";
if (subString (source, 0, 5, dest))
{
printf ("%s\n", dest);
}
char* someString = "abcdedgh";
char* otherString = 0;
otherString = (char*)malloc(5+1);
memcpy(otherString,someString,5);
otherString[5] = 0;
UPDATE:
Tip: A good way to understand definitions is called the right-left rule (some links at the end):
Start reading from identifier and say aloud => "someString is..."
Now go to right of someString (statement has ended with a semicolon, nothing to say).
Now go left of identifier (* is encountered) => so say "...a pointer to...".
Now go to left of "*" (the keyword char is found) => say "..char".
Done!
So char* someString; => "someString is a pointer to char".
Since a pointer simply points to a certain memory address, it can also be used as the "starting point" for an "array" of characters.
That works with anything .. give it a go:
char* s[2]; //=> s is an array of two pointers to char
char** someThing; //=> someThing is a pointer to a pointer to char.
//Note: We look in the brackets first, and then move outward
char (* s)[2]; //=> s is a pointer to an array of two char
Some links:
How to interpret complex C/C++ declarations and
How To Read C Declarations
You'll need to allocate memory for the new string otherString. In general for a substring of length n, something like this may work for you (don't forget to do bounds checking...)
char *subString(char *someString, int n)
{
char *new = malloc(sizeof(char)*n+1);
strncpy(new, someString, n);
new[n] = '\0';
return new;
}
This will return a substring of the first n characters of someString. Make sure you free the memory when you are done with it using free().
You can use snprintf to get a substring of a char array with precision:
#include <stdio.h>
int main()
{
const char source[] = "This is a string array";
char dest[17];
// get first 16 characters using precision
snprintf(dest, sizeof(dest), "%.16s", source);
// print substring
puts(dest);
} // end main
Output:
This is a string
Note:
For further information see printf man page.
You can treat C strings like pointers. So when you declare:
char str[10];
str can be used as a pointer. So if you want to copy just a portion of the string you can use:
char str1[24] = "This is a simple string.";
char str2[6];
strncpy(str1 + 10, str2,6);
This will copy 6 characters from the str1 array into str2 starting at the 11th element.
I had not seen this post until now, the present collection of answers form an orgy of bad advise and compiler errors, only a few recommending memcpy are correct. Basically the answer to the question is:
someString = allocated_memory; // statically or dynamically
memcpy(someString, otherString, 5);
someString[5] = '\0';
This assuming that we know that otherString is at least 5 characters long, then this is the correct answer, period. memcpy is faster and safer than strncpy and there is no confusion about whether memcpy null terminates the string or not - it doesn't, so we definitely have to append the null termination manually.
The main problem here is that strncpy is a very dangerous function that should not be used for any purpose. The function was never intended to be used for null terminated strings and it's presence in the C standard is a mistake. See Is strcpy dangerous and what should be used instead?, I will quote some relevant parts from that post for convenience:
Somewhere at the time when Microsoft flagged strcpy as obsolete and dangerous, some other misguided rumour started. This nasty rumour said that strncpy should be used as a safer version of strcpy. Since it takes the size as parameter and it's already part of the C standard lib, so it's portable. This seemed very convenient - spread the word, forget about non-standard strcpy_s, lets use strncpy! No, this is not a good idea...
Looking at the history of strncpy, it goes back to the very earliest days of Unix, where several string formats co-existed. Something called "fixed width strings" existed - they were not null terminated but came with a fixed size stored together with the string. One of the things Dennis Ritchie (the inventor of the C language) wished to avoid when creating C, was to store the size together with arrays [The Development of the C Language, Dennis M. Ritchie]. Likely in the same spirit as this, the "fixed width strings" were getting phased out over time, in favour for null terminated ones.
The function used to copy these old fixed width strings was named strncpy. This is the sole purpose that it was created for. It has no relation to strcpy. In particular it was never intended to be some more secure version - computer program security wasn't even invented when these functions were made.
Somehow strncpy still made it into the first C standard in 1989. A whole lot of highly questionable functions did - the reason was always backwards compatibility. We can also read the story about strncpy in the C99 rationale 7.21.2.4:
The strncpy function
strncpy was initially introduced into the C library to deal with fixed-length name fields in
structures such as directory entries. Such fields are not used in the same way as strings: the
trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter
5 names to null assures efficient field-wise comparisons. strncpy is not by origin a “bounded
strcpy,” and the Committee preferred to recognize existing practice rather than alter the function
to better suit it to such use.
The Codidact link also contains some examples showing how strncpy will fail to terminate a copied string.
I think it's easy way... but I don't know how I can pass the result variable directly then I create a local char array as temp and return it.
char* substr(char *buff, uint8_t start,uint8_t len, char* substr)
{
strncpy(substr, buff+start, len);
substr[len] = 0;
return substr;
}
strncpy(otherString, someString, 5);
Don't forget to allocate memory for otherString.
#include <stdio.h>
#include <string.h>
int main ()
{
char someString[]="abcdedgh";
char otherString[]="00000";
memcpy (otherString, someString, 5);
printf ("someString: %s\notherString: %s\n", someString, otherString);
return 0;
}
You will not need stdio.h if you don't use the printf statement and putting constants in all but the smallest programs is bad form and should be avoided.
Doing it all in two fell swoops:
char *otherString = strncpy((char*)malloc(6), someString);
otherString[5] = 0;
char largeSrt[] = "123456789-123"; // original string
char * substr;
substr = strchr(largeSrt, '-'); // we save the new string "-123"
int substringLength = strlen(largeSrt) - strlen(substr); // 13-4=9 (bigger string size) - (new string size)
char *newStr = malloc(sizeof(char) * substringLength + 1);// keep memory free to new string
strncpy(newStr, largeSrt, substringLength); // copy only 9 characters
newStr[substringLength] = '\0'; // close the new string with final character
printf("newStr=%s\n", newStr);
free(newStr); // you free the memory
Try this code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* substr(const char *src, unsigned int start, unsigned int end);
int main(void)
{
char *text = "The test string is here";
char *subtext = substr(text,9,14);
printf("The original string is: %s\n",text);
printf("Substring is: %s",subtext);
return 0;
}
char* substr(const char *src, unsigned int start, unsigned int end)
{
unsigned int subtext_len = end-start+2;
char *subtext = malloc(sizeof(char)*subtext_len);
strncpy(subtext,&src[start],subtext_len-1);
subtext[subtext_len-1] = '\0';
return subtext;
}

Typecast:LPCTSTR to Char * for string concatenate operation

Can u Give solution for this code of typecasting, LPCTSTR(here lpsubkey) to Char*
for below code snippet ,
char* s="HKEY_CURRENT_USER\\";
strcat(s,(char*)lpSubKey);
printf("%S",s);
here it makes error of access violation ,so what will be the solution for that?.
...thanks in advance
There are several issues with your code that might well lead to the access violation. I don't think any have anything to do with the cast you mentioned.
You are assigning a pointer to the first element of a fixed size char array to a char * and then attempt to append to this using strcat. This is wrong as there is no additional space left in the implicitly allocated string array. You will need to allocate a buffer big enough to hold the resulting string and then copy the string constant in there before calling strcat. For example, like so:
char *s = (char*)malloc(1024 * sizeof(char));
strcpy(s, "HKEY_CURRENT_USER\\");
strcat(s, T2A(lpSubKey));
printf("%s", s);
free(s);
Please note that the fixed size array I'm allocating above is bad practise. In production code you should always determine the correct size of the array on the go to prevent buffer overflows or use functions like strncat and strncpy to ensure that you are not copying more data into the buffer than the buffer can hold.
These are not the same thing. What are you trying to do?
The problem is you are trying to append to a string that you have not reserved memory for.
Try:
char s[1024] = "HKEY_CURRENT_USER";
strcat(s,(char*)lpSubKey );
printf("%S",s);
Do be careful with the arbitrary size of 1024. If you expect your keys to be much longer your program will crash.
Also, look at strcat_s.
ATL and MFC has set of macros to such conversion, where used next letters:
W - wide unicode string
T - generic character string
A - ANSI character string
OLE - BSTR string,
so in your case you need T2A macros
strcat does not attempt to make room for the combination. You are overwriting memory that isn't part of the string. Off the top of my head:
char *strcat_with_alloc(char *s1, char *s2)
{
if (!s1 || !s2) return NULL;
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
char *dest = (char *)malloc(len1 + len2 + 1);
if (!dest) return NULL;
strcpy(dest, s1);
strcat(dest, s2);
return dest;
}
now try:
char* s="HKEY_CURRENT_USER\\";
char *fullKey = strcat_with_alloc(s,(char*)lpSubKey);
if (!fullKey)
printf("error no memory");
else {
printf("%S",fullKey);
free(fullKey);
}

Resources