Sign in to follow this  
raydog

strcat, strcpy, strcrap functions

Recommended Posts

I think I have a memory leak problem, but I can't track it down. It has to do with the runtime string functions strcat() and strcpy(). Strcat is cutting off my string. It's never the full string I'm expecting. I even get stranger results when I move the declaration of certain strings around. I'm just doing simple things like: CHAR temp1[256]; CHAR temp2[256]; strcpy( temp1, "Some text" ); strcpy( temp2, "Some text" ); strcat( temp1, temp2 ); This is almost impossible to debug. When I put in some logging functions, the leak goes away. When I take them out, I get corrupted strings again. And I don't want to use strncat or strncpy. I've had really bad experiences with those functions. Can't use MFC CString either. I'm just wondering can these two functions be internally corrupted somehow, so even if I call them with 'good' strings, they will still give me back bad results? Does anyone write their own string functions because they get corrupted strings from using these runtime functions?

Share this post


Link to post
Share on other sites
It is highly unlikely that the functions are internally corrupted. If adding logging functions appears to make the problem go away, it is usually an indication that your are overwriting a local pointer or writing too many bytes to a local string/array. The problem may be with asking strcpy/strcat to copy more bytes than you've allocated for the target. Or it could be something somewhere else in your code.

Share this post


Link to post
Share on other sites
Try these simple examples...if they work then it's your code that's wrong.

/* strcpy example */
#include <stdio.h>
#include <string.h>

int main ()
{
char str1[]="Sample string";
char str2[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,"copy successful");
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
return 0;
}


Output:
str1: Sample string
str2: Sample string
str3: copy successful

/* strcat example */
#include <stdio.h>
#include <string.h>

int main ()
{
char str[80];
strcpy (str,"strings ");
strcat (str,"have been ");
strcat (str,"concatenated.");
puts (str);
return 0;
}


Output:
strings have been concatenated.

Share this post


Link to post
Share on other sites
The problem must have to do with some other portion of your code. When I compiled this, it worked:

#include <stdio.h>
#include <stdlib.h>

int main()
{
char temp1[256];
char temp2[256];
strcpy(temp1, "Some Text ");
strcpy(temp2, "Some Text");
strcat(temp1,temp2);
printf("%s\n",temp1);
printf("%s\n",temp2);
return 0;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by raydog
I am using the MSVC++ 6.0 optimizer. I always set it to maximize speed.
I wrote my own strcat and strcpy functions, and it works now. How strange
is that?


There is nothing wrong with the snippet of code you posted, and strcpy and strcat cannot be "internally corrupted". I think the fact that you have had "bad experiences" with strncpy and strncat when those functions are safer versions of strcpy and strcat indicates something about your code.

Anyway, I agree that it is strange (though not suprising) that your bugs went away even though you didn't fix them.

Share this post


Link to post
Share on other sites
Ah, voodoo coding practices.

If I was staffing a team, I wouldn't hire you. You didn't solve the problem, electing to rewrite instead - and to rewrite a standard library function at that! - and you didn't even debug properly.

Take responsibility for your code rather than seeking to blame someone or something else at the first opportunity.

Share this post


Link to post
Share on other sites
Quote:
Original post by Oluseyi
Ah, voodoo coding practices.

If I was staffing a team, I wouldn't hire you. You didn't solve the problem, electing to rewrite instead - and to rewrite a standard library function at that! - and you didn't even debug properly.


I agree.

Quote:
Original post by Oluseyi
Take responsibility for your code rather than seeking to blame someone or something else at the first opportunity.


This is probably the best advice any software engineer can take on board. It can take years to erase the mentality of "I am right, let us look for the problem elsewhere first", but once you have, you will be light years ahead of many others in your field.

Share this post


Link to post
Share on other sites
Though Oluseyi's comments may have seemed harsh, I do believe that he has made the point that needed to be made.
The more experience you gain, the more you realise that all those times you blamed the compiler, it was you're own fault all along.

Those strxxx functions do not actually allocate any memory. They therefore cannot leak as such. A likely explanation is that your code has a buffer overrun that is writing over the value of some pointer, thus losing the address and trying to free garbage instead later.

You're problem IS caused by your own code. These so called bad experiences you've had in the past with strnxxx functions, and now strcpy functions, are almost certainly the result of other bugs you have written.
Don't underestimate the value of the knowledge gained, by spending countless hours tracking down the cause of mysterious bugs. You must understand the problem in order to not repeat it.

I highly recommend reading the book "Writing Solid Code" By Steve Maguire.

Share this post


Link to post
Share on other sites
Quote:
Original post by Oluseyi
Ah, voodoo coding practices.

If I was staffing a team, I wouldn't hire you. You didn't solve the problem, electing to rewrite instead - and to rewrite a standard library function at that! - and you didn't even debug properly.

Take responsibility for your code rather than seeking to blame someone or something else at the first opportunity.


Problem gone = problem solved :)

Share this post


Link to post
Share on other sites
Quote:
Original post by raydog
Problem gone = problem solved :)

You'll be gone next... problem solved.

(by the way, I was recently made redundant... not because of my coding practices of course)

Share this post


Link to post
Share on other sites
Quote:
Original post by raydog
Problem gone = problem solved :)


Problem gone != problem solved.

Why? Because this error will cause corruption in the future. I have no idea what you're writing, but in the end, this bug will bite your ass so hard, you can't sit for a week.

You just hacked yourself away from your problem. Your code is still flawed, but the bug just got covered with some dirt. Just like you can't exterminate weed by throwing a new layer of ground over it. The weed will just grow back. And this bug will rise too. Maybe not now, but perhaps in a 6 months, after your code got very large and way more advanced that it is now.

And then, it will be even harder to fix.

Toolmaker

Share this post


Link to post
Share on other sites
Quote:
Original post by antareus
I've just begun playing with unit tests and I'm seeing how they can slash bug hunting times in half or more.
I was also recently playing with unit testing (CPPUnit) and I decided to write a unit test for my CRC calculator. I expected the unit test to report no problems but was shocked to find that the code was full of bugs.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
You're problem IS caused by your own code. These so called bad experiences you've had in the past with strnxxx functions, and now strcpy functions, are almost certainly the result of other bugs you have written.
Quote:
Original post by JohnBolton
I think the fact that you have had "bad experiences" with strncpy and strncat when those functions are safer versions of strcpy and strcat indicates something about your code.
While I doubt that there's a bug in the implementation of strn* functions there are widespread misconceptions about their behaviour.

So let me issue a serious warning about them. These functions are supposed to be used with fixed-width fields, not null terminated strings!
And thus instead of null terminating too long results they simply truncate the output without any termination. One safer(ish) way of handling this problem is to feed the functions with the buffer's size minus one and manually set it's last character to null, another is to use snprintf() if your compiler supports it.

Share this post


Link to post
Share on other sites
strlcat and strlcpy are also good functions to use - they operate more along the lines of what most people expect from the strnxxx functions. That is, they *always* null terminate and the length parameter is considered to be the entire length of the output buffer, not just the length it's allowed to deal with.

Unfortunately the MS compiler doesn't have these functions, though it's not hard to find the source for them.

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
... One safer(ish) way of handling this problem is to feed the functions with the buffer's size minus one and manually set it's last character to null, another is to use snprintf() if your compiler supports it.

Minor corrections: strncat does guarantee that the result is terminated. But like strncpy, snprintf does not guarantee that the result is terminated.

Share this post


Link to post
Share on other sites
Quote:
Original post by raydog
Problem gone = problem solved :)
The problem isn't gone. It's just obscured. Now, every time anything goes wrong with your code, among everything else, you will need to ask yourself "is this caused by whatever's wrong with my code that made me write my own strcat and strcpy?" This is why good programmers debug problems rather than avoid them: because they're experienced enough to know the value of a robust framework.

[Edited by - Sneftel on February 15, 2005 5:50:18 PM]

Share this post


Link to post
Share on other sites
But the problem is more complicated than that. I'm using somebody else's library.
And it's buggy to begin with, so there is nothing I can do about it except compile and pray.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
Minor corrections: strncat does guarantee that the result is terminated. But like strncpy, snprintf does not guarantee that the result is terminated.
I've just double checked with VC 2k3 and GCC, with interesting results.
It appears that VC's strncat() does force termination while GCC's does not. On the other hand GCC's snprintf() does force termination while VC's _snprintf does not.

Could someone please triple check these findings? snprintf() hasn't been standardised long so I guess it's implementations could differ, however I have a hard time believing that someone would screw up their C89 standard library or even leave such issues implementation defined.

Lets hope I'm wrong, otherwise I'll have to go back and fix some code..

Share this post


Link to post
Share on other sites
Quote:
Original post by raydog
And I don't want to use strncat or strncpy. I've had really bad experiences with
those functions. Can't use MFC CString either.


I don't suppose you can use std::string? :s

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
Quote:
Original post by JohnBolton
Minor corrections: strncat does guarantee that the result is terminated. But like strncpy, snprintf does not guarantee that the result is terminated.
... It appears that VC's strncat() does force termination while GCC's does not. On the other hand GCC's snprintf() does force termination while VC's _snprintf does not. Could someone please triple check these findings? ...
strncat:
GCC
...A single null character is also always appended to to, so the total allocated size of to must be at least size + 1 bytes longer than its initial length...
VC++
... The resulting string is terminated with a null character ...

snprintf (_snprintf in VC++):
You are correct. GCC always terminates the result, but VC++ does not. So, you can't assume that snprintf always terminates the result (at least not in portable code).

Share this post


Link to post
Share on other sites
Quote:
Original post by raydog
But the problem is more complicated than that. I'm using somebody else's library.
And it's buggy to begin with, so there is nothing I can do about it except compile and pray.


Write tests for the library to find you what the bugs are exactly.

Either ask the person who's library it is to fix them, or fix them yourself, or write a wrapper round the library so that it behaves correctly.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this