strcat

E

Eric Kaplan

why the following code will crash?

int main()
{
char* str = "aa";
strcat (str, "hello");
cout << str << "\n";
strcat (str, "you1");
cout << str << "\n";

return 0;
}
 
A

acehreli

why the following code will crash?

int main()
{
char* str = "aa";
strcat (str, "hello");
cout << str << "\n";
strcat (str, "you1");
cout << str << "\n";

return 0;

}

1) When you find the documentation for strcat, you will notice that it
includes some requirements like "The strings may not overlap, and the
dest must have enough space for the result."

In your example, there is no space for the result.

2) String literals are constant objects, which means that the
characters that they contain may not be modified. The fact that it is
possible to initialize pointers to non-const with string literals is
for backward compatibility.

You should not take advantage of that in new code. So instead of
writing

char* str = "aa";

write

const char* str = "aa";

Ali
 
S

Sharad

2) String literals are constant objects, which means that the
characters that they contain may not be modified. The fact that it is

IIRC, this statement is not true. String literals as defined in the C
Standard are not defined as constant. Yet, modifying them leads to undefined
behavior. This is what I recollect from C89 (I have to admit that it's been
quite some time, so I may be wrong). Most of the Unix compilers place string
literals in a read only region, so modifying them gets a segmention
violation there.

Sharad
 
R

Ron Natalie

Eric said:
why the following code will crash?

int main()
{
char* str = "aa";

This is a deprecated conversion from a 3 element array of const char
(holding the values a a and \0) to pointer to (single) character.
strcat (str, "hello");

This attempts to write hello on to the end of the chars starting
at str. The h is written into read only storage, the ello\0 is
written outside of any allocated memory.
cout << str << "\n";
strcat (str, "you1");
cout << str << "\n"; \
}

char* is not a string type.
strcat doesn't allocate any memory. You are expected to have enough
allocated memory in the bytes pointed to by the first argument to
hold the concatenation of both strings.

This is C++ and you shouldn't be playing with C's old and busted
string functions but the C++ new hotness string type.

std::string str = "aa";
str += "hello";
cout << str << "\n"

see.
 
U

utab

You should not take advantage of that in new code. So instead of
writing

char* str = "aa";

write

const char* str = "aa";

Ali

For the code at hand, this does not help to recover the segfault
though.

Still you will be trying to change a const char array. So why bother,
use strings without the implementation details of pointers ;),
pointers/arrays are evil :), as far as possible I refrain to use
them.
 
S

Sharad

utab said:
For the code at hand, this does not help to recover the segfault
though.

It does in some way. The program won't compile now.
Still you will be trying to change a const char array. So why bother,
use strings without the implementation details of pointers ;),
pointers/arrays are evil :), as far as possible I refrain to use
them.

Yes, in C++ you are better off with std::string and std::vector.

Sharad
 
A

acehreli

For the code at hand, this does not help to recover the segfault
though.

The OP used 'cout', so I'm assuming this is C++. (Heck, the group is
clc++!) So the compiler is required to reject passing str to strcat
now. ;)

Ali
 
A

acehreli

IIRC, this statement is not true. String literals as defined in the C
Standard are not defined as constant. Yet, modifying them leads to undefined
behavior.

So they are constant.
This is what I recollect from C89 (I have to admit that it's been
quite some time, so I may be wrong).

Same here, but luckily we are on a C++ forum and discussing a C++
code. :)
Most of the Unix compilers place string
literals in a read only region, so modifying them gets a segmention
violation there.

That's because string literals are constant. :)

Ali
 
S

Sharad

So they are constant.

I don't think so. I will need to go back to the C Standard to verify that.
Same here, but luckily we are on a C++ forum and discussing a C++
code. :)

Nah, C++ has inherited a lot from C. Most C programs are valid C++ programs
also. And the behavior we are talking about is the inherited behavior.
That's because string literals are constant. :)

Read above.

Sharad
 
I

Ian Collins

Sharad said:
I don't think so. I will need to go back to the C Standard to verify that.
2.13.4 of the C++ standard states that a string literal has type "array
of n const char".
 
I

Ian Collins

The OP used 'cout', so I'm assuming this is C++. (Heck, the group is
clc++!) So the compiler is required to reject passing str to strcat
now. ;)
Only if str is "const char*".
 
J

James Kanze

IIRC, this statement is not true. String literals as defined
in the C Standard are not defined as constant.

String literals are defined by the C++ standard as having type
char const[n+1], where n is the number of characters in the
literal. There is a hacky implicit conversion, however, to
allow using them to initialize a char*. In C (not really
relevant here, of course), they are defined as having type
char[n+1], but as being non-modifiable. Again, the type is
compromized to allow them to be used to initialize a char*.

The reason for the compromize is historical: C didn't always
have const, and before const existed, `char* s = "literal";'
was, of course, a common idiom. Naturally, no one would write
this in new code, today, but there is a strong desire to not
break existing code.
Yet, modifying them leads to undefined behavior. This is what
I recollect from C89 (I have to admit that it's been quite
some time, so I may be wrong).

That's correct for C90.
Most of the Unix compilers place string literals in a read
only region, so modifying them gets a segmention violation
there.

Most Unix compilers I know have an option so you can choose
whether they are really modifiable or not. In K&R C, they were
explicitly modifiable, programs were written for Unix which
depended on it, and compiler vendors don't want to break code,
even if the code is shit.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top