I have this part in a code:
char* data="My name is: ";
I would like to add to this the argv[1] argument with represents a name. How to do this in c code? I've tried strcpy and strcat but i have segmentation fault when Ipcp do this:
strcpy(data,argv[1]);
Can anyone please help?
Also why this: data=data+argv[1] is not working?
You need to provide some memory, where the result of the concatentation can be stored into. For example:
char buffer[1024];
strcpy(buffer, "My name is: ");
strcat(buffer, argv[1]);
Note, however, that this is error prone: if the value of argv[1] combined with the prefix string is longer than 1024 characters, this produces a buffer overflow. So, maybe something like this:
char* prefix = "My name is: ";
int length = strlen(prefix) + strlen(argv[1]) + 1;
char* buffer = malloc(length);
if (!buffer) abort();
else
{
strcpy(buffer, prefix);
strcat(buffer, argv[1]);
/* Do something with buffer here. And don't
* forget to free it, once you no longer need
* it. This is C -- no garbage collection. */
free(buffer);
}
Also why this: data=data+argv[1] is not working?
About this one - in C data and argv are nothing more than pointers to address in the memory containing your string. You can't concatenate strings(char*) this way.
I suggest to take a look at the string library and maybe a bit more in C as a whole.
Memory for data will be allocated in read-only section. so modifying will cause issue.
where in memory are string literals ? stack / heap?
+ operator will not do concat as you thought.
strcat() function is implemented in string.h.
You cant append to th data pointer because there are no space in it
char result_data [1024];
char* data="My name is: ";
strcat(result_data, data);
strcat(result_data, argv[1]);
Related
I made a smaller scenario of my bigger problem. What I try to do is pass a string to a function which will make a new string out of it. However I ran into some problems.
I have defined string as
typedef char string[1024];
Then I have a function that takes a string and makes a new string which get filled with the old string and a dot char
string* add_sth_to_string(char* msg){
string* newStr=malloc(sizeof(string)); // malloc a newStr
strcpy(*newStr, msg); // copying msg to newStr
char buff[1024]; // making a buffer
strcat(buff, "."); // adding a dot to buffer
strcat(buff, *newStr); // adding msg to buffer
strcpy(*newStr, buff); // copying buffer to newStr
return newStr;
}
Then in main I try to use this function 3 times for a new string each time:
for (i=0; i<3; i++){
string* newStr;
newStr=add_sth_to_string("test");
printf("str: %s\n", *newStr);
free(newStr);
// can even printf here
}
This is the weird output I get:
str: .test
str: .test.test
str: .test.test.test
When I would expect to get:
str: .test
str: .test
str: .test
Anyone who can point out what is happening? Something else I find weird is that I can printf the value of newStr just after I have freed it.
You are using buff without initializing it. Try:
char buff[1024];
buff[0] = 0;
Something else I find weird is that I can printf the value of newStr
just after I have freed it.
Accessing memory after freeing it is undefined behavior. Typically, for performance reasons, free doesn't zero the memory.
That's 2 cases of undefined behavior in the same question + one really weird typedef. Keep it up!
Try changing
strcat(buff, ".");
into
strcpy(buff, ".");
Or alternativly initialise buff when declaring it like so:
char buff[1024] = "";
You should clear content of buf[1024] each iteration.
UPDATE
Because buf[1024] will not be zero-ed automatically when allocated on the stack. And you choose strcat to concatenate two string, which will find a \0-terminate. Thus if buf contains some default value, it will introduce obfuscated output.
Use buf[1024] = ""; to allocate a buffer will correct the output.
string* newStr=malloc(sizeof(string)); // malloc a newStr
strcpy(*newStr, msg); // copying msg to newStr
This will also crash. string is a pointer so sizeof of it will return 4 or 8, not what you wanted to do.
Ok, forget about my remark you made a typedef, but I let it here to show you why the typedef is a bad idea. At first glance it obfuscated the fact that it was an array and not a pointer, on a 30 line program it's not a probleme, but when you have to maintain a 200 000 lines project (as I do), you will start to hate these kind of things.
Another point, you should avoid to work with fixed sized strings of 1024 bytes. 1024 is not that big (even homecomputer of the 80s had screens bigger than that) and for the majority if strings, which are fairly short, you spoil a lot of memory for nothing.
Here is my code :
char *name, name_log="log-";
------getting 'name' from user-----
strcat(name_log, name);
char ext[] = ".log";
strcat(name_log, ext);
What i need to end up with is name_log = "log-'name'.log" but Im getting a segmentation fault error :((. What am I doing wrong and how can I fix it ? Thx
For a start, if this is your code:
char *name, name_log="log-";
then name_log is a char, not a char pointer.
Assuming that's a typo, you cannot append to string literals like that. Modifications to string literals are undefined behaviour.
For a variable sized string, as user appears to be, probably the safest option is to allocate another string large enough to hold the result, something like:
char *name, *name_log = "log-", *ext = ".log";
// Do something to allocate and populate name
char *buffer = malloc (strlen (name_log) + strlen (name) + strlen (ext) + 1);
if (buffer == NULL) {
// Out of memory.
} else {
strcpy (buffer, name_log);
strcat (buffer, name);
strcat (buffer, ext);
// Do something with buffer.
free (buffer);
}
The malloc ensures you have enough space to do all the string operations safely, enough characters for the three components plus a null terminator.
string literals get allocated a fixed amount of memory, generally in a read only section, you instead need to use a buffer.
char buffer[64] = "log-";
strncat(buffer,".log",32);
On a side note, strcat is generally unsafe, you need to use something that that checks the size of the buffer it uses or with limits on what it can concatenate, like strncat.
A completely different solution would be this:
const char *prefix = "log-";
const char *suffix = ".log";
// There's a "char *name" somewhere
int size_needed;
char *result;
size_needed = snprintf(NULL, 0, "%s%s%s", prefix, name, suffix);
result = malloc(size_needed + 1);
snprintf(result, size_needed + 1, "%s%s%s", prefix, name, suffix);
// "result" now contains the desired string.
The nice thing about snprintf is that it returns the number of characters it would write if there was enough space. This can be used by measuring upfront how much memory to allocate which makes complicated and error-prone calculations unnecessary.
If you happen to be on a system with asprintf, it's even easier:
char *result = NULL /* in case asprintf fails */;
asprintf(&result, "log-%s.log", name);
// "result" must be released with "free"
you need to allcocate memory. You cannot add to a string in this way as the string added goes to memory which hasnt been allocated.
you can do
char[20] strarray;
strcat(strarray, "log-");
strcat(strarray, "abcd");
the name_log is pointed at a static place: "log-", which means is could not be modified, while as the first parameter in strcat(), it must be modifiable.
try changing name_log's type char* into char[], e.g.
char[20] name_log = "log-";
numCheck is number between 1-1000. This code gives me a segfault only when I collect the results of sprintf in charcheck. If I simply use sprintf without using the results, I don't get a seg fault. What's happening here?
char * numString;
int charcheck = sprintf(numString, "%d", numCheck);
You need to provide your own memory for sprintf. Also, don't use sprintf, but rather snprintf:
char buf[1000] = {0};
snprintf(buf, 999, ....);
Alternatively you can allocate memory dynamically:
char * buf = new char[BUFSIZE];
snprintf(buf, BUFSIZE-1, ...);
/* ... */
delete[] buf;
The pointer given as the first parameter to sprintf is expected to point to a memory location where sprintf should write the formatted string.
In this case you didn't initialize numString to point to some memory you allocated for the formatted string. Since numString isn't initialized it might point anywhere, and in your case trying to write the formatted output to that location results in a segmentation fault.
The first argument to sprintf must point to a valid buffer. You have a char* but it points to garbage.
Change your code to:
char numString[80] = { };
int charcheck = sprintf(numString, "%d", numCheck);
So that numString actually points to a valid buffer (of 80 characters in this example, all elements of which are initialised to 0).
It would also be good to use snprintf so you can pass the size of your buffer to it, which will help prevent buffer overflows:
const int bufsize = 80;
char numString[bufsize] = { };
int charcheck = snprintf(numString, bufsize - 1, "%d", numCheck);
Notice that you subtract one from the buffer size that you pass to snprintf because you don't want it to use the very last slot, which you want to make sure is NULL to denote the end of the string.
You need to allocate space for the result such as
char numString[50];
int charcheck = sprintf(numString, "%d", numCheck);
In your case the interal workings of sprintf are trying to reference NULL which is the default value for a pointer in your case.
The most straightforward thing to do is to use an array as above, e.g.,
char numString[80] = { };
suggested by Seth, Jesus and Kerrek.
I think the last answer from sth is a good explanation: "the first parameter to sprintf is expected to point to a memory location where sprintf should write the formatted string." So apart from using an array of characters, which would force the allocation of memory for the string, you can also use this:
char *numstring = (char*) malloc(80);
This should let you explicitly free the allocated memory when it is no longer needed.
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);
}
Okay so I have the following Code which appends a string to another in C#, note that this is Just an example, so giving alternative string concatination methods in C# is not nessesary, this is just to simplify the example.
string Data = "";
Data +="\n\nHTTP/1.1 " + Status_code;
Data += "\nContent-Type: " + Content_Type;
Data += "\nServer: PT06";
Data += "\nContent-Length: " + Content_Lengt;
Data += "\nDate: " + Date;
Data += "\n" + HTML;
Now I'd like to do the exact same thing in C and I'm trying to do this the following way
time_t rawtime;
time ( &rawtime );
char *message = "\n\nHTTP/1.1 ";
message = strcat(message, Status_code);
message = strcat(message, "\nContent-Type: ");
message = strcat(message, Content_Type);
message = strcat(message, "\nServer: PT06");
message = strcat(message, "\nContent-Length: ");
message = strcat(message, Content_Lengt);
message = strcat(message, "\nDate: ");
message = strcat(message, ctime(&rawtime));
message = strcat(message, "\n");
message = strcat(message, HTML);
Now, this gives me a Segment fault, I know why, I access and read on memory that i shouldn't. But the question is, how do i solve it? Could I use string.h and just do it the same way that I did in C#?
Change
char *message = "\n\nHTTP/1.1 ";
to
char message[1024];
strcpy(message,"\n\nHTTP/1.1 ");
and you should be ok, up to a total message length of 1023.
Edit: (as per mjy's comment). Using strcat in this fashion is a great way of getting buffer overflows. You could readily write a small function that checks the size of the buffer and length of incoming string addition to overcome this, or use realloc on a dynamic buffer. IMO, the onus is on the programmer to check correct buffer sizes where they are used, as with sprintfs and other C strings functions. I assume that C is being used over C++ for performance reasons, and hence STL is not an option.
Edit: As per request from Filip's comment, a simple strcat implementation based on a fixed size char buffer:
char buffer[MAXSIZE] = "";
int mystrcat(char *addition)
{
if (strlen(buffer) + strlen(addition) + sizeof(char) >= MaxSize)
return(FAILED);
strcat(buffer,addition);
return(OK);
}
Using dynamic allocation:
char *buffer = NULL;
int mystrcat(char *addition)
{
buffer = realloc(buffer, strlen(buffer) + strlen(addition) + sizeof(char));
if (!buffer)
return(FAIL);
strcat(buffer, addition);
return(OK);
}
In this case you have to free your buffer manually when you are finished with it. (Handled by destructors in C++ equivalents)
Addendum (Pax):
Okay, since you didn't actually explain why you had to create message[1024], here it is.
With char *x = "hello", the actual bytes ('h','e','l','l','o',0) (null on the end) are stored in an area of memory separate from the variables (and quite possibly read-only) and the variable x is set to point to it. After the null, there's probably something else very important. So you can't append to that at all.
With char x[1024]; strcpy(x,"hello");, you first allocate 1K om memory which is totally dedicated to x. Then you copy "hello" into it, and still leave quite a bit of space at the end for appending more strings. You won't get into trouble until you append more than the 1K-odd allowed.
End addendum (Pax):
I wonder why no one mentioned snprintf() from stdio.h yet. That's the C way to output multiple values and you won't even have to convert your primitives to strings beforehand.
The following example uses a stack allocated fixed-sized buffer. Otherwise, you have to malloc() the buffer (and store its size), which would make it possible to realloc() on overflow...
char buffer[1024];
int len = snprintf(buffer, sizeof(buffer), "%s %i", "a string", 5);
if(len < 0 || len >= sizeof(buffer))
{
// buffer too small or error
}
Edit: You might also consider using the asprintf() function. It's a widely available GNU extension and part of TR 24731-2 (which means it might make it into the next C standard). The example from above would read
char * buffer;
if(asprintf(&buffer, "%s %i", "a string", 5) < 0)
{
// (allocation?) error
}
Remember to free() the buffer when done using it!
Start from using the safer strncat function. In general always use the safer 'n' functions that will not overflow if the size of a string is bigger than a specific size.
In C you need to take care of string sizes yourself. So you need to know how big the resulting string will be and accommodate for it. If you know the sizes of all the strings at the left side, you should create a buffer big enough to hold the resulting string.
message points to a char const[] that you can't write to, yet that's exactly where strcat is writing. You need to malloc() a sufficiently large buffer.
As said previously, you have to write to a sufficiently large buffer. Unfortunately, doing so is a lot of extra work. Most C applications that deal with strings use a dynamically resizable string buffer for doing concatenations.
glib includes an implementation of this, glib strings, which I recommend using for any application that uses strings heavily. It makes managing the memory easier, and prevents buffer overflows.
Have not seen any mention of the strlcpy, strlcat function, which is similar to the 'n' functions except also takes into account the trailing 0. Both take a third argument indicating the maximum length of the output buffer and are found in string.h.
example:
char blah[]="blah";
char buffer[1024];
strlcpy(buffer,"herro!!!",sizeof(buffer));
strlcat(buffer,blah,sizeof(buffer));
printf("%s\n",buffer);
Will output "herro!!!blah"
char blah[]="blah";
char buffer[10];
strlcpy(buffer,"herro!!!",sizeof(buffer));
strlcat(buffer,blah,sizeof(buffer));
printf("%s\n",buffer);
will output "herro!!!b" due to the limited size of buffer[], with no segfaulting. ^^
Only problem is not all platforms seem to include it in their libc (such as linux ._.), most all BSD varients DO seem to have it.
In that case, code for both functions can be found here and easily added: strlcpy, strlcat,
the rest of string.h
The safe way to do this in classic C style is:
char *strconcat(char *s1, char *s2)
{
size_t old_size;
char *t;
old_size = strlen(s1);
/* cannot use realloc() on initial const char* */
t = malloc(old_size + strlen(s2) + 1);
strcpy(t, s1);
strcpy(t + old_size, s2);
return t;
}
...
char *message = "\n\nHTTP/1.1 ";
message = strconcat (message, Status_code);
message = strconcat (message, "\nContent-Type: ");
Now you can say a lot of bad things about it: it's inefficient, it fragments your memory, it's ugly ... but it's more or less what any language with a string concatenation operator and C type (zero-terminated) strings will do (except that most of these languages will have garbage collection built-in).