web rocker
web rocker

Reputation: 217

c program segment error from GCC compiler: concatenate two strings

The following code raise segment error from GCC compiler:

char *str1 = "India";
char *str2 = "BIX";
char *str3;
str3 = strcat(str1, str2);
printf("%s %s\n", str3, str1);

The problem is str3=strcat(str1, str2).

So my question is: for GCC Compiler, it forbids two pointers pointing to the same thing?

Upvotes: 0

Views: 256

Answers (5)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76395

What you should have written, code-wise, answers your question:

char *str1 = "India";
char *str2 = "BIX";
//should have been
const char *str1 = "India";
const char *str2 = "BIX";

The variables str1 and str2 are being assigned the address in memory where the string CONSTANTS India and BIX are located. This memory is read-only. You are trying to concatenate these two strings using strcat. Ok, look at what it does:

strcat(str1, str2);
       /\   take this
       || copy  ||
       ===========
        add to end

This requires str1 to point to a block of memory big enough to accomodate both itself and the chars that you're concatenating onto it. In case of string literals, this is never the case.
Also remember how I wrote your code with the const storage class specifier? Now look at strcat's prototype:

char * strcat(char * destination, const char *source);

The function expects the first argument to be a regular char *, not a const. This tells you the function will attempt to change the memory the pointer points to. As others have pointed out, and I mentioned above: the memory your str1 pointer points to is read only, hence the segfault.

What you could write is:

char str1[15] = "India";
const char *str2 = "BIX";
strcat(str1, str2);

That ought to work. Note that strcat does not check/prevent overflow. The size of the destination memory should be big enough to accomodate strlen(source) + strlen(destination) + 1. Using strncat instead would be better, still! It allows you to specify a max number of chars to be concatenated onto the destination string:

size_t free_space = 15;
char str1[free_space] = "India";
const char *str2 = "BIX";
free_space -= strlen(str1) + 1;//add 1 here, to ensure we'll have room for the terminating \0 char
char *str3 = strncat(
    str1,
    str2,
    free_space
);
//now we've concatenated something onto our string, keep track of free space left:
free_space -= strlen(str2);//dangerous, though -> size_t is unsigned, perhaps best do:

size_t src_len = strlen(str2);
char *str3 = strncat(
    str1,
    str2,
    free_space
);
if (src_len >= free_space)
    free_space = 0;
else
    free_space -= src_len;

Upvotes: 1

Jabberwocky
Jabberwocky

Reputation: 50774

You need this:

char str1[100] = "India";    // str1 is an array for maximum 100 chars, initialized with "India"
char *str2 = "BIX";          // str2 is a pointer to the string literal "BIX" (read only)
char *str3 ;                 // str3 is pointer to char

str3 = strcat(str1, str2);   // appends "BIX" to "India" in the str1 buffer and puts str1 in str3
printf("%s %s\n", str3, str1);

Upvotes: 0

ajay
ajay

Reputation: 9680

Trying to change a string literal invokes undefined behaviour. It's read-only even though it's not const qualified.

str3 = strcat(str1, str2);

The above statement calls strcat which has prototype

char *strcat(char *dest, const char *src);

Here dest is a pointer to a buffer which is large enough for the string pointed to by src to be appended to it. str1 is a pointer to a string literal. Therefore, strcat will read the characters of the string str2 and write them beyond the string str1 which is illegal. You don't need to save the return value of strcat in a separate char * variable because it modifies its first argument. So after strcat returns, string pointed to by src is appended to the one pointed to by dest. You should change your code to

#define MAX_SIZE 40

char str1[MAX_SIZE] = "India";
const char *str2 = "BIX";

// str1 must be large enough for 
// str2 to be appended to it
strcat(str1, str2);
printf("%s %s\n", str2, str1);

Upvotes: 1

Gangadhar
Gangadhar

Reputation: 10516

strcat

char * strcat ( char * destination, const char * source );

Concatenate strings Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.

destination Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

But your destination is not pointer to an array(that is large enough to contain the concatenated resulting string) it is a pointer to sting literal, reason for segmentation fault is you are going to write in read only memory locations

Upvotes: 1

Lee Duhem
Lee Duhem

Reputation: 15121

Usually, string literals will be put in read-only memory region, your call to strcat() will try to write to this read-only memory region, therefore segment fault.

Upvotes: 1

Related Questions