This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed last year.
What's wrong with this code?:
int main(int argc, char ** argv) {
char strs[] = "What will be printed?";
char *str1;
char *str2;
strs[5] = '\0';
str1 = strs;
strcpy(str2, str1);
printf("%s\n", str2);
return 1;
}
I want it to print "What", instead i get segmentation fault.
I believe it has something to do with the strcpy(str2, str1);, but what is the explanation for that? The signature of strcpy is char* strcpy(char* destination, const char* source); and that's exactly what i did.
Could you explain that to me?
Your destination string is not initialized - it has no memory reserved for itself. An attempt to write to it causes invalid memory access (you're trying to overwrite something completely random and unplanned) and is followed by a segmentation fault.
One clean way to initialize a string is to define a global macro variable that just sets the largest size of strings you plan on using in your code,
#define MAXBUF 100
Then in your main you can simply write:
char str2[MAXBUF];
And your program will work. Alternative is to use dynamic memory allocation which you will likely learn about soon.
#include <stdio.h>
#include <string.h>
int main() {
char *src = "What will be printed?";
char dest[100];
int START = 0; // start of copy
int LENGTH = 5; // length of copy
// copies up to LENGTH characters from the string pointed to, by src to dest. In a case where the length of src is less than that of LENGTH, the remainder of dest will be padded with null bytes.
strncpy(dest, &src[START], LENGTH);
printf("%s\n", dest);
return 0;
}
This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 3 years ago.
I'm learning pointers in C, using Linux. I'm trying to use the strcat function, but it doesn't work and I don't understand why.
I'm passing a username to the main as an argument because I need to concatenate and put a number 1 in the first position of this username. For example if the I got as argument username123 I need to convert this to 1username123
I got this code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char *finalUser;
userTemp = argv[1]; //I got the argument passed from terminal
finalUser = "1";
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
The code compiles, but I got a segmentation fault error and doesn't know why. Can you please help me going to the right direction?
It is undefined behaviour in C to attempt to modify a string literal (like "1"). Often, these are stored in non-modifiable memory to allow for certain optimisations.
Let's leave aside for the moment the fact that your entire program can be replaced with:
#include <stdio.h>
int main(int argc, char *argv[]){
printf("User: 1%s\n", (argc > 1) ? argv[1] : "");
return 0;
}
The way you ensure you have enough space is to create a buffer big enough to hold whatever you want to do. For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
// Check args provded.
if (argc < 2) {
puts("User: 1");
return 0;
}
// Allocate enough memory ('1' + arg + '\0') and check it worked.
char *buff = malloc(strlen(argv[1]) + 2);
if (buff == NULL) {
fprintf(stderr, "No memory\n");
return 1;
}
// Place data into memory and print.
strcpy(buff, "1");
strcat(buff, argv[1]);
printf("User: %s\n", buff);
// Free memory and return.
free(buff);
return 0;
}
What you shouldn't do is to allocate a fixed size buffer and blindly copy in the data provided by a user. That's how the vast majority of security problems occur, by people overwriting buffers with unexpected data.
I'm trying to use the strcat function, but it doesn't work and I don't understand why.
For starters, you really shouldn't use strcat(). Use strlcat() instead. The "l" version of this and other functions take an extra parameter that let you tell the function how large the destination buffer is, so that the function can avoid writing past the end of the buffer. strcat() doesn't have that parameter, so it relies on you to make sure the buffer is large enough to contain both strings. This is a common source of security problems in C code. The "l" version also makes sure that the resulting string is null-terminated.
The code compiles, but I got a segmentation fault error and doesn't know why.
Here's the prototype for the function: char *strcat( char *dest, const char *src );
Now, you're calling that essentially like this: strcat("1", someString);. That is, you're trying to append someString to "1", which is a string constant. There's no extra room in "1" for whatever string is in someString, and because you're using a function that will happily write past the end of the destination buffer, your code is effectively writing over whatever happens to be in memory next to that string constant.
To fix the problem, you should:
Switch to strlcat().
Use malloc() or some other means to allocate a destination buffer large enough to hold both strings.
Unlike in other languages there is no real string type in C.
You want this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char finalUser[100]; // finalUser can contain at most 99 characters
userTemp = argv[1]; //I got the argument passed from terminal
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
or even simpler:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
char finalUser[100]; // finalUser can contain at most 99 characters
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, argv[1]); //To concatenate argv[1] to finalUser
printf("User: %s\n",finalUser);
return 0;
}
Disclaimer: for the sake of brevity this code contains a fixed size buffer and no check for buffer overflow is done here.
The chapter dealing with strings in your C text book should cover this.
BTW you also should check if the program is invoked with an argument:
int main(int argc, char *arg[]){
if (argc != 2)
{
printf("you need to provide a command line argument\n");
return 1;
}
...
You're missing some fundamentals about C.
finalUser = "1";
This is created in "read-only" memory. You cannot mutate this. The first argument of strcat requires memory allocated for mutation, e.g.
char finalUser[32];
finalUser[0] = '1';
I wrote this code
#include <stdio.h>
int main()
{
char String[] = "Hello the world!";
char *pointer = String;
int i;
printf(" %s\n", pointer);
pointer = "Helllooooo the worlldddddd";
printf("Hello %s\n", pointer);
printf("Hello %s\n", String);
return 0;
}
but I can't understand how this line works fine.
pointer = "Helllooooo the worlldddddd";
but I got this output
Hello the world!
Hello Helllooooo the worlldddddd
Hello Hello the world!
As you see it couldn't change String value but it shows more than the original number of characters. Shouldn't this cause a buffer overflow? Won't that destroy other variables?
When you write the line
pointer="Helllooooo the worlldddddd";
you are not saying "take the array pointed at by pointer and overwrite its contents with the string "Helllooooo the worlldddddd"," but rather "change which string pointer points at so that it's now pointing at the string ""Helllooooo the worlldddddd"." This accounts for why you're seeing the original string printed out when you directly print String - you never actually modified it. As a result, you don't need to worry about overflowing your array here, since you're not actually writing anything to it.
On the other hand, if you wrote
strcpy(pointer, "Helllooooo the worlldddddd");
which actually does copy the contents of the new string into the buffer pointed at by pointer, then you would have a buffer overflow, which would be a problem. But notice that this is a very different operation that explicitly says "please copy the contents of this string to this location" rather than "change where this pointer points."
you have initialize a pointer which point to String "Hello the world " char *pointer=String; so far so good .
first printf printf(" %s\n",pointer);, you have printed the pointer which point to "Hello the world".
then you set the pointer to point anew string "Hellloooooo the worllddddd" pointer="Helllooooo the worlldddddd";.
then you have printed the pointer which point in this case to "Hellloooooo the worllddddd"printf("Hello %s\n",pointer); .
last printf you have printed the string "Hello the world" printf("Hello %s\n",String);.
Note:.
((takecare that you have printed in second printf("Hello %s\n",String); and third printf printf("Hello %s\n",String); the string hello which will be printed before the value of the pointer or the string))
#include <stdio.h>
int main()
{
char String[]="Hello the world"; // the string
char *pointer=String; // pointer to string
char i; //counter
printf(" %s\n",pointer); // print current value of pointer
pointer="number of char"; // new value to replace the string
for (i=0;i<14;i++) // you cannot change the content of array without using loop
{
String[i] = pointer[i]; // char i in string = ti char i in pointer
}
printf("Hello %s\n",pointer); // print value of pointer
printf("Hello %s\n",String); // print value of string
return 0;
}
i think that what are you trying to do.
One more quick option for you to consider when manipulating strings:
The string function strdup(...); allows the copying of an existing string into a newly created string in one easy step. (or at least one in which all the complexity has been abstracted away):
char *pointer = strdup("Helllooooo the worlldddddd");
The new string pointer can now be used to contain any string up to len long, where len is defined as:
int len = strlen(pointer);//len is 26 after using strdup(...); above
So for example, because your example string is shorter than len:
char String[]="Hello the world!";//length is 16
you could copy it into pointer without a buffer overflow:
strcpy(pointer, String);
Strings created using strdup(...): need to be free'd to avoid memory leaks. Call the following when you are finished using pointer:
free(pointer);
I'm working in C, and I have to concatenate a few things.
Right now I have this:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Now if you have experience in C I'm sure you realize that this gives you a segmentation fault when you try to run it. So how do I work around that?
In C, "strings" are just plain char arrays. Therefore, you can't directly concatenate them with other "strings".
You can use the strcat function, which appends the string pointed to by src to the end of the string pointed to by dest:
char *strcat(char *dest, const char *src);
Here is an example from cplusplus.com:
char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");
For the first parameter, you need to provide the destination buffer itself. The destination buffer must be a char array buffer. E.g.: char buffer[1024];
Make sure that the first parameter has enough space to store what you're trying to copy into it. If available to you, it is safer to use functions like: strcpy_s and strcat_s where you explicitly have to specify the size of the destination buffer.
Note: A string literal cannot be used as a buffer, since it is a constant. Thus, you always have to allocate a char array for the buffer.
The return value of strcat can simply be ignored, it merely returns the same pointer as was passed in as the first argument. It is there for convenience, and allows you to chain the calls into one line of code:
strcat(strcat(str, foo), bar);
So your problem could be solved as follows:
char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);
Avoid using strcat in C code. The cleanest and, most importantly, the safest way is to use snprintf:
char buf[256];
snprintf(buf, sizeof(buf), "%s%s%s%s", str1, str2, str3, str4);
Some commenters raised an issue that the number of arguments may not match the format string and the code will still compile, but most compilers already issue a warning if this is the case.
Strings can also be concatenated at compile time.
#define SCHEMA "test"
#define TABLE "data"
const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry = // include comments in a string
" SELECT * " // get all fields
" FROM " SCHEMA "." TABLE /* the table */
" WHERE x = 1 " /* the filter */
;
Folks, use strncpy(), strncat(), or snprintf().
Exceeding your buffer space will trash whatever else follows in memory!
(And remember to allow space for the trailing null '\0' character!)
Also malloc and realloc are useful if you don't know ahead of time how many strings are being concatenated.
#include <stdio.h>
#include <string.h>
void example(const char *header, const char **words, size_t num_words)
{
size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
char *message = (char*) malloc(message_len);
strncat(message, header, message_len);
for(int i = 0; i < num_words; ++i)
{
message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
message = (char*) realloc(message, message_len);
strncat(strncat(message, ";", message_len), words[i], message_len);
}
puts(message);
free(message);
}
Best way to do it without having a limited buffer size is by using asprintf()
char* concat(const char* str1, const char* str2)
{
char* result;
asprintf(&result, "%s%s", str1, str2);
return result;
}
If you have experience in C you will notice that strings are only char arrays where the last character is a null character.
Now that is quite inconvenient as you have to find the last character in order to append something. strcat will do that for you.
So strcat searches through the first argument for a null character. Then it will replace this with the second argument's content (until that ends in a null).
Now let's go through your code:
message = strcat("TEXT " + var);
Here you are adding something to the pointer to the text "TEXT" (the type of "TEXT" is const char*. A pointer.).
That will usually not work. Also modifying the "TEXT" array will not work as it is usually placed in a constant segment.
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
That might work better, except that you are again trying to modify static texts. strcat is not allocating new memory for the result.
I would propose to do something like this instead:
sprintf(message2, "TEXT %s TEXT %s", foo, bar);
Read the documentation of sprintf to check for it's options.
And now an important point:
Ensure that the buffer has enough space to hold the text AND the null character. There are a couple of functions that can help you, e.g., strncat and special versions of printf that allocate the buffer for you.
Not ensuring the buffer size will lead to memory corruption and remotely exploitable bugs.
Do not forget to initialize the output buffer. The first argument to strcat must be a null terminated string with enough extra space allocated for the resulting string:
char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string );
// null_terminated_string has less than 1023 chars
As people pointed out string handling improved much. So you may want to learn how to use the C++ string library instead of C-style strings. However here is a solution in pure C
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void appendToHello(const char *s) {
const char *const hello = "hello ";
const size_t sLength = strlen(s);
const size_t helloLength = strlen(hello);
const size_t totalLength = sLength + helloLength;
char *const strBuf = malloc(totalLength + 1);
if (strBuf == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
strcpy(strBuf, hello);
strcpy(strBuf + helloLength, s);
puts(strBuf);
free(strBuf);
}
int main (void) {
appendToHello("blah blah");
return 0;
}
I am not sure whether it is correct/safe but right now I could not find a better way to do this in ANSI C.
It is undefined behaviour to attempt to modify string literals, which is what something like:
strcat ("Hello, ", name);
will attempt to do. It will try to tack on the name string to the end of the string literal "Hello, ", which is not well defined.
Try something this. It achieves what you appear to be trying to do:
char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);
This creates a buffer area that is allowed to be modified and then copies both the string literal and other text to it. Just be careful with buffer overflows. If you control the input data (or check it before-hand), it's fine to use fixed length buffers like I have.
Otherwise, you should use mitigation strategies such as allocating enough memory from the heap to ensure you can handle it. In other words, something like:
const static char TEXT[] = "TEXT ";
// Make *sure* you have enough space.
char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);
// Need to free message at some point after you're done with it.
The first argument of strcat() needs to be able to hold enough space for the concatenated string. So allocate a buffer with enough space to receive the result.
char bigEnough[64] = "";
strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);
/* and so on */
strcat() will concatenate the second argument with the first argument, and store the result in the first argument, the returned char* is simply this first argument, and only for your convenience.
You do not get a newly allocated string with the first and second argument concatenated, which I'd guess you expected based on your code.
You can write your own function that does the same thing as strcat() but that doesn't change anything:
#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
static char buffer[MAX_STRING_LENGTH];
strncpy(buffer,str1,MAX_STRING_LENGTH);
if(strlen(str1) < MAX_STRING_LENGTH){
strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
}
buffer[MAX_STRING_LENGTH - 1] = '\0';
return buffer;
}
int main(int argc,char *argv[]){
printf("%s",strcat_const("Hello ","world")); //Prints "Hello world"
return 0;
}
If both strings together are more than 1000 characters long, it will cut the string at 1000 characters. You can change the value of MAX_STRING_LENGTH to suit your needs.
You are trying to copy a string into an address that is statically allocated. You need to cat into a buffer.
Specifically:
...snip...
destination
Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.
...snip...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
There's an example here as well.
Assuming you have a char[fixed_size] rather than a char*, you can use a single, creative macro to do it all at once with a <<cout<<like ordering ("rather %s the disjointed %s\n", "than", "printf style format"). If you are working with embedded systems, this method will also allow you to leave out malloc and the large *printf family of functions like snprintf() (This keeps dietlibc from complaining about *printf too)
#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
const char *s, \
*a[] = { __VA_ARGS__,NULL}, \
**ss=a; \
while((s=*ss++)) \
while((*s)&&(++offset<(int)sizeof(buf))) \
*bp++=*s++; \
if (offset!=sizeof(buf))*bp=0; \
}while(0)
char buf[256];
int len=0;
strcpyALL(buf,len,
"The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
write(1,buf,len); //outputs our message to stdout
else
write(2,"error\n",6);
//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
write(1,buf,len); //outputs both messages
else
write(2,"error\n",6);
Note 1, you typically wouldn't use argv[0] like this - just an example
Note 2, you can use any function that outputs a char*, including nonstandard functions like itoa() for converting integers to string types.
Note 3, if you are already using printf anywhere in your program there is no reason not to use snprintf(), since the compiled code would be larger (but inlined and significantly faster)
int main()
{
char input[100];
gets(input);
char str[101];
strcpy(str, " ");
strcat(str, input);
char *p = str;
while(*p) {
if(*p == ' ' && isalpha(*(p+1)) != 0)
printf("%c",*(p+1));
p++;
}
return 0;
}
Try something similar to this:
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[])
{
// Insert code here...
char firstname[100], secondname[100];
printf("Enter First Name: ");
fgets(firstname, 100, stdin);
printf("Enter Second Name: ");
fgets(secondname,100,stdin);
firstname[strlen(firstname)-1]= '\0';
printf("fullname is %s %s", firstname, secondname);
return 0;
}
This was my solution
#include <stdlib.h>
#include <stdarg.h>
char *strconcat(int num_args, ...) {
int strsize = 0;
va_list ap;
va_start(ap, num_args);
for (int i = 0; i < num_args; i++)
strsize += strlen(va_arg(ap, char*));
char *res = malloc(strsize+1);
strsize = 0;
va_start(ap, num_args);
for (int i = 0; i < num_args; i++) {
char *s = va_arg(ap, char*);
strcpy(res+strsize, s);
strsize += strlen(s);
}
va_end(ap);
res[strsize] = '\0';
return res;
}
but you need to specify how many strings you're going to concatenate
char *str = strconcat(3, "testing ", "this ", "thing");
I am writing a program that takes a command line argument and user input, and calculates the difference between the two characters (cryptography). I would like to pass my argument into a variable within the program, but am unable to do so.
#include <stdio.h>
int main(int argc, char** argv) {
char plain[2];
char cipher[2]; /*locations of plain and cipher text*/
char *ppoint; /*pointers to plain and cipher*/
char *cpoint;
scanf("%s",plain);
*ppoint=plain[0]; /* ppoint points to 1st character in plain*/
cipher=argv[1]; /* cpoint points to first argument character*/
*cpoint=cipher[1];
printf("%s %d \n",ppoint,plain);
printf("%s %d \n",cpoint,cipher);
return 0;
}
For line 14, I am met with a compiler error ,
(cipher=argv[1];) " Incompatible types in assignment "
I have been experimenting with many methods such as type casting but I can not get anything to work.
I would like the two last lines of my program to output the actual character and their respective ASCII values. Please help me past this block!
UPDATE:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char plain;
char *cipher; /*locations of plain and cipher text*/
int *ppoint; /*pointers to plain and cipher*/
int *cpoint;
scanf("%s",plain);
*ppoint=(int) plain; /* ppoint points to 1st character in plain*/
cipher=argv[1]; /* cpoint points to first argument character*/
*cpoint=(int) cipher;
printf("%s %d \n",plain);
printf("%s %d \n",cipher);
return 0;
}
I used type casting to fix any compiler errors. However upon running the program and in putting a value for 'plain', I am met with a segmentation fault. I have looked long and hard but cannot see where this memory error is occurring. Please help.
You are attempting to assign a char pointer to a char array, which is not allowed. You'll need to copy the argument some other way. For example, you could use strcpy:
strcpy(cipher,argv[1]);
Alternatively, you could make cipher be a char pointer instead if you never modify it.
const char *cipher;
...
cipher = argv[1];
try using,
ppoint=(int) plain; /* ppoint points to 1st character in plain*/
Without the '*', as you cannot use the de-referencing operator on the pointer variable as the pointer doesn't point to any location yet.