Solved

String Handling in "C"

Posted on 2002-03-13
21
284 Views
Last Modified: 2010-04-15
Hello

# include<stdio.h>
# include<string.h>

int main (void)
{
     char str[9] = "hello";
     char str1[]=  "world";
     
     strcat(str, str1);
     printf("%s", str);
}

I expected the above program to give "Application Error"
since str can hold only 9 characters, but we try to
have 10 chars (helloworld) after doing strcat. But to
my surprise the program ran successfully without any error. I used Microsoft visual c++  on win NT to test
this. Can you explain why it didn't give error?


b)Is it possible to use strcat for a variable that is
declared as char *x="test" using pointers (or)
is strcat always used with array of characters declared using [] rather than character pointer.


Thanks
Sridhar
0
Comment
Question by:puji
  • 6
  • 6
  • 4
  • +3
21 Comments
 
LVL 4

Expert Comment

by:newmang
Comment Utility
Sridhar

This behaviour is one of the downsides of the freedoms provided by C. There is no concept of length checking so when you did your strcat the data in str1 would have been copied into the memory area allocated to str and would have written past the end of the area allocated into str, in the process overwriting whatever happened to be there.

The printf worked because a string is an array of characters terminated by a null (0x00). You were lucky in this case because there was obviously nothing of consequence in the memory area following str but if there had been significant information there then you r program may have crashed or exhibited odd behaviour.

This is a frequent cause of strange behaviour in programs as a strcat at one place in the application may over-write a variable used somewhere else in the program. It is also a classic cause of program cracking and is very dangerous.

You really should use the strncat() function where you define both the source string, the destination string and the number of characters to copy - strncat(source, dest, sizeof(dest)-1) to avoid this problem.

The answer to b) is yes. In fact when you typed strcat(str, str1) you were passing to the strcat function the address of str and the address of str1 which is what iy would do if you used explicit pointers. So the following are valid.

char str[10]="xxxx";
char str1[10]="yyyy"
strncat(str,str1,9);

char str[10]="xxxx";
char str1[10]="yyyy"
strncat(&str[0], &str1[0],9);

char * pstr;
char * pstr1;
pstr=(char *)malloc(10);
pstr=(char *)malloc(10);
strcpy(pstr,"xxxx");
strcpy(pstr1,"yyyy");
strncpy(pstr,pstr1,9);
.
.
free(pstr);
free(pstr1);

I hope this helps - Gavin Newman
0
 
LVL 5

Expert Comment

by:nebeker
Comment Utility
One of the reasons it worked is because when you allocated the 9 characters for the 'str[9]', you really got more than 9 characters :)

Behind the scenes, the memory manager that handles malloc and the list of free pages generally trys to return memory on even 4 byte (or multiples of 4 byte) boundaries.

For example, consider this simple program:
---------------------------------------------------------

#include <stdio.h>

int main( void )
{
    char *p1 = (char *) malloc( 1 );
    char *p2 = (char *) malloc( 1 );

    printf( "p1 = %p, p2 = %p\n", p1, p2 );
    return 0;
}
---------------------------------------------------------

At first glance, you might think that the memory allocated for pointer "p2" is going to be 1 byte after pointer "p1".  But when I ran this program, I got the following output:

p1 = 0xa010320, p2 = 0xa010330

which shows a difference of 0x10, which tells me that malloc is aligning things on a 16 byte boundary.  This means that I could write an extra 15 bytes to pointer "p1" and not blow up my program.

Of course, you can't always rely on this, since you have no idea where the boundaries will be....
0
 
LVL 12

Expert Comment

by:pjknibbs
Comment Utility
nebeker: However, malloc() has nothing to do with this situation because malloc() is not used to allocate memory for a declaration like char str[9]. In this case, since str[9] is a local variable, the compiler will simply assign 9 extra bytes on the stack when entering the function by shifting the stack pointer, which is a LOT faster than allocating stuff using malloc(). (You should remember that malloc() is a C run-time library function, whereas array variables are a much lower-level part of the C language).

puji: newmang gave a perfect explanation. I'd be willing to bet that if you inspect the value of str1 after doing your strcat() you'll find it's changed, because the end of the concatenated string has overwritten the start of it.
0
 

Author Comment

by:puji
Comment Utility
Thanks for the response, one more thing regarding strncat,
Does strncat add a '\n' at the end of the
string?
0
 
LVL 5

Expert Comment

by:nebeker
Comment Utility
Well, the compiler may *assign* 9 bytes, but the NEXT variable on the stack will be aligned on a 4 byte boundary, which gives pretty much the same effect, since you can easily write another 3 bytes into that char[9] variable without blowing anything up.

By the way, array variables aren't a lower part of C.  C doesn't know anything about arrays, period.  It treats them as a base pointer + an offset, that's it.

0
 
LVL 5

Expert Comment

by:nebeker
Comment Utility
puji -

strncat will never append a \n character at the end of the string (strcat won't either).  I think you're confusing this with the '\0' (nul) character, which strncat will append to the destination string.
0
 
LVL 12

Expert Comment

by:pjknibbs
Comment Utility
nebeker: True, but pointers are still a much lower level part of the language than malloc() is. If you try compiling a simple C program to assembly code you will NOT find any calls to malloc() in the part of the code which allocates local variables.

As for stack items being aligned on four byte boundaries, there's absolutely no reason why the compiler needs to do this. If you're using PUSH and POP to set and retrieve stack values you're limited to four byte boundaries, true, but the compiler will access local variables by reading from a direct offset to the EBP register--no PUSH or POP operations are involved. It might well be that the compiler WILL doubleword-align the variables for faster access, but there's absolutely nothing forcing it to do so.
0
 

Expert Comment

by:rpatna
Comment Utility
if u see the code of strcat();
then u can understand urself only
why it not give "Application Error"
and why it run successfully without any error.
0
 

Author Comment

by:puji
Comment Utility
To nebeker
>>strncat will never append a \n character at the end of >>the string (strcat won't either).  I think you're
>>confusing this with the '\0' (nul) character, which >>strncat will append to the destination string.


Hi nebeker

I just wrongly typed as '\n'. But I meant '\0', null character.

So Is it true that all c compilers, (or atleast the one MSVC uses) adds a '\0' to the destination string after doing a concatenation.

Thanks
puji
0
 
LVL 4

Expert Comment

by:newmang
Comment Utility
Yes
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 12

Expert Comment

by:pjknibbs
Comment Utility
Yes, because that's how the strcat() function is defined and written in all cases.
0
 

Expert Comment

by:osnat
Comment Utility
a) The program does not check run-time errors. U can also use free on a pointer and then use it. U can do what ever u want with pointers, but it is your responsibility ! If the memory is not used by the OS of any other application, then your program will run. BUT this is a chance u, as a programmer, can not take.

b)regarding strcat: since strcat add str2 at the end of str1, u can not define str1 as char*. and why not?!
when u define char* str1 = "test"; u are allocating 5 chars for str1 (strlen("test") + 1 for null terminator).
And str1 shoule be long enough to hold the combination of str1 and str2. there for: the compiler will have no problems with it, since strcat takes (char* str1, const char*str2), but in run-time your program will crash.
0
 
LVL 5

Expert Comment

by:nebeker
Comment Utility
osnat -

Your answer adds absolutely nothing to the discussion - why did you even bother to post this as an answer instead of a comment?
0
 
LVL 12

Expert Comment

by:pjknibbs
Comment Utility
nebeker: Because he's seen there's been no activity in this thread for three days and he thinks he can camp out in it and get an automatic answer awarded to him, I imagine.
0
 

Author Comment

by:puji
Comment Utility
Hello All,

Thanks for your repsonses.
I believe I haven't worded by question .
Actually I wanted to know
Is there any difference in the '\0' null character
getting appended with respect to strcat and strncat().

Why Iam specific about this case is I came across a
program where STRNCAT function worked when I added a
null character to it, but it did NOT work (gave an error)
without the explicit additon of '\0'.

Thanks
puji
0
 
LVL 5

Expert Comment

by:nebeker
Comment Utility
puji -

What platform and compiler are you using?  It is possible that strncat doesn't append a null in some cases -- depending on your particular compiler, that is...
0
 
LVL 4

Expert Comment

by:newmang
Comment Utility
puji

It would be simple for you to add the trailing null anyway as follows

len=strlen(str1);
len+=strlen(str2);
strncat(str1,str2,sizeof(str1));
if(len<sizeof(str1))
    str1[len-1]=0x00;
else
    str1[sizeof(str1)-1]=0x00;

Cheers - Gavin
0
 

Author Comment

by:puji
Comment Utility
Hi

Iam using MSVC that comes with Visual Studio 6.0 on
Windows NT 4.0 Platform.

0
 
LVL 5

Accepted Solution

by:
nebeker earned 50 total points
Comment Utility
As long as both strings are null terminated, you won't have a problem with strncat.

Here's the reference page from Microsoft on strncat:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_strncmp.2c_.wcsncmp.2c_._mbsncmp.asp

It says:

The strncat function appends, at most, the first count characters of strSource to strDest. The initial character of strSource overwrites the terminating null character of strDest. If a null character appears in strSource before count characters are appended, strncat appends all characters from strSource, up to the null character. If count is greater than the length of strSource, the length of strSource is used in place of count. The resulting string is terminated with a null character. If copying takes place between strings that overlap, the behavior is undefined.


If you've run into a problem with this before, it most likely happened because the 2nd string wasn't null terminated...
0
 

Author Comment

by:puji
Comment Utility
Thanks To All of You, But I would like to give points to
nebeker since it clarified my doubt.

Thanks
Puji
0
 

Author Comment

by:puji
Comment Utility
Thanks nebeker

Bye
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now