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).
Related
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
char buff[10]={0};
char buff1[6]="xxxxx";
sprintf(buff,"My name is %s");
is this a correct array initialization for buff (ie.10)? or I need to initialize with 17.
If you're going to write over it with sprintf then it doesn't need to contain anything in particular, it just needs to be large enough to hold the data.
In other words the = {0} is sufficient, and actually optional in this case.
PSA: DO NOT USE functions like sprintf that are missing a length argument. Instead use snprintf and related functions where there is a length argument. Buffer overflow bugs are a huge problem in C if you do not take proper precautions.
The code you should have in C is roughly:
size_t buff_size = 255;
char buff[buff_size];
char* name = "Aadhi";
snprintf(buff, buff_size, "My names is %s", name);
Where that contains not only a placeholder argument but, importantly, the value that should be used.
In C++ you should skip this entirely and instead:
std::string name = "Aadhi";
std::string message = "My name is " + name;
Where std::string avoids almost all of the problems with buffer overflow bugs.
C++ 20 introduces a new std::format feature which works an awful lot like sprint but without all the buffer overflow issues:
std::string name = "Aadhi";
std::string message = std::format("My name is {}", name);
I have used to split C strings by many means: strstr, strsep, strtok, strtok_r...Here is a case where I have a delimiter and I want to split the string. Having only done so in languages such as Java, JavaScript, Python..it seems verbose and clumsy. It feels a bit fragile..Is there a better way to do this? I feel that I have to put a lot of trust in arithmetic.
char message [] = "apples are better than bananas...But good as grapes?";
char *delimiter_location = strstr(message, "...");
int m1_strlen = delimiter_location - message;
int m1_chararr_size = m1_strlen + 1;
char message_1 [m1_chararr_size];
memset(message_1, '\0', m1_chararr_size);
strncpy(message_1, message, m1_strlen);
printf("message: %s\n", message);
printf("message 1: %s", message_1);
You could use a library for regular expressions, like discussed here.
Your code can be streamlined into:
char message [] = "apples are better than bananas...But good as grapes?";
char *delimiter_location = strstr(message, "...");
int m1_strlen = delimiter_location - message;
// Not every C standard and every compiler supports dynamically sized arrays.
// In those cases you need to use malloc() and free().
// Or even better: strdup() or strndup().
char message_1[m1_strlen + 1];
// NB no need to call memset() because the space is written to immediately:
strncpy(message_1, message, m1_strlen);
message_1[m1_strlen] = '\0'; // This ensures a terminated string.
printf("message: %s\n", message);
printf("message 1: %s\n", message_1);
I get a lot of strcat lines in my code. Is there a better way to concatenate strings in C?
char material[50]; // it is defined before this code.
char result[10000];
strcpy(result, "// Assign new material to worldGlobe\n");
strcat(result, "shadingNode -asShader lambert -n ");
strcat(result, material);
strcat(result, ";\n");
You could use a format string in conjunction with snprintf() (safe compared to sprintf()):
snprintf(result, 10000,
"// Assign new material to worldGlobe\nshadingNode -asShader lambert -n %s;\n",
material);
strcat is only really suitable for really small strings; it has several problems for anything non-trivial, such as:
Due to the Schlemiel The Painter problem, strcat is O(n) over the length of the input strings, that is, the longer your strings, the longer each concatenation takes. This is because strcat has to walk the entire string to find its end. To solve this, store the length of the string along with the string data, which will allow you to jump directly to the end of the string.
It does not do any bounds checking. If you strcat too much onto the end of a string, it will happily write past the end of the string, producing a segfault in the best case, a severe security vulnerability in the worst, and most likely some bugs that will make you bash your head against the wall. strncat partially solves this problem, as long as you pass it the correct size of the destination buffer.
If your destination buffer is too small, neither strcat nor strncat will increase its size: you'll have to do this yourself.
There are two practical solutions in your situation:
a) The Tower Of Hanoi algorithm: Build a stack of strings. If a new string is shorter than the stack top, push it onto the stack. If it's longer, pop off the top, concatenate, and repeat the process with the result. When you're done pushing, concatenate what's on the stack. This is what std::stringstream in C++ or StringBuilder in .NET do, and if you look around, I'm sure you'll find a suitable implementation in C.
b) Write your strings directly to a stream. What you're outputting looks a lot like code - why not write it to a file directly?
What about
sprintf(result, "// Assign new material to worldGlobe\nshadingNode -asShader lambert -n %s;\n\0", material);
Try stpcpy; see link. Your sample code becomes:
char material[50]; // it is defined before this code.
char result[10000], *p = result;
p = stpcpy(p, "// Assign new material to worldGlobe\n");
p = stpcpy(p, "shadingNode -asShader lambert -n ");
p = stpcpy(p, material);
p = stpcpy(p, ";\n");
This function is available in Linux; the man page for stpcpy on my system states:
This function is not part of the C or POSIX.1 standards, and is not customary on Unix systems, but is not a GNU invention either. Perhaps it comes from MS-DOS.
If you don't have it, it is easy enough to write:
char *stpcpy(char *restrict dst, const char *restrict src) {
return strcpy(dst, src) + strlen(src);
}
This assumes you are aware of the dangers of strcpy.
C is mostly a do-it-yourself language.
Now that you know how to concat strings, you should write your own function to make it easier.
I'd suggest something like:
char* str_multicat(char* result, ...);
And call it something like:
str_mutlicat(result, "// Assign new material to worldGlobe\n",
"shadingNode -asShader lambert -n ",
material,
";\n",
NULL);
(hint, if you don't know the ... syntax, look into va_arg, va_start, va_end)
It would by pretty straight forward to build a string buffer struct that will keep track of the current position in your buffer, and combine that with vsprintf to get a catf(). The function vsnprintf() (assuming it's available) is just like printf, except it takes a va_list instead of ... after the format string.
This approach has the advantage over other answers that it lets you 'cat' from anywhere in your code that has access to the struct without explicitly carrying around the current length or recalculating each time it like strcat does.
Here's a rough sketch free of charge.....
/* Note: the typedef is for the pointer, not the struct. */
typedef struct StrBufStruct {
char * buffer,
size_t size,
size_t pos
} * StrBuf;
/* Create a new StrBuf. NOTE: Could statically allocate too. */
StrBuf newStrBuf(size_t size){
StrBuf sb;
sb = malloc( sizeof(struct StrBufStruct) );
sb->size = size;
sb->pos = 0;
sb->buffer = malloc( size );
/* TODO: ALWAYS CHECK YOUR MALLOC!!! */
}
int sbcatf( StrBuf b, char * fmt, ... )
{
va_list ap;
int res;
if( b->pos < b->size )
{
va_start(ap,fmt);
res = vsnprintf( b->buffer[b->pos], b->size - b->pos, fmt, ap );
b->pos += res;
va_end();
} else {
/* If you want to get really fancy, use realloc so you don't have to worry
about buffer size at all. But be careful, you can run out of memory. */
}
}
/* TODO: Write a free/delete function */
int main(int argc, char **argv){
int i;
/* initialize your structure */
StrBuf sb = newStrBuf(10000);
/* concatenate numbers 0-999 */
for(i=0; i < 1000; i++){
sbcatf(sb, "I=%d\n", i);
}
/* TODO: whatever needs to be done with sb->buffer */
/* free your structure */
deleteStrBuf(sb);
}
Also note that if all you're trying to do is make a really long string but want to be able to have line breaks in your code, this is usually acceptable, although I won't personally guarantee portability. I also use the technique to separate strings at "\n" line breaks to make the code look like the resulting string really would.
const char * someString = "this is one really really really really"
"long stttttttttrrrrrrrrrrrrrrrrrrrriiiiiiiiiiinnnnnnngggggg"
" because the compiler will automatically concatenate string"
" literals until we reach a ';' after a \" character";
You could have a function that returns a pointer to the end of the string, and use that end pointer in future calls. That'd eliminate a bunch of the extra "first, find the end of the string" stuff.
char* faster_cat(char* dest, const char* src)
{
strcpy(dest, src);
return dest + strlen(src);
}
Use like:
char result[10000];
char *end = &result[0];
result[0] = '\0'; // not strictly necessary if you cat a string, but why not
end = faster_cat(end, "// Assign new material to worldGlobe\n");
end = faster_cat(end, "shadingNode -asShader lambert -n ");
end = faster_cat(end, material);
end = faster_cat(end, ";\n");
// result now contains the whole catted string
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);
}