2

I want to assign a char* to char* , if I use strcpy I get several run time memory problem so I fix it by simple assignment using = operator. Can any one explain what should prepare before using strcpy to avoid memory issues.

EDIT:

int Function(const char* K,char* FileIN,char* FileOut,int DC)
{   
    char *fic_in,*n_fic,*fic_out,*fic_dec;

    unsigned char k[17];

        fic_in = (char*)malloc(60*sizeof(char));

        strcpy((char*)k,K);

        //strcpy(fic_in,FileIN);  //I remove this one
        fic_in=FileIN;            //and replace it by this
      ...
Oumaya
  • 655
  • 4
  • 18
  • 43
  • 1
    http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy – Ankur Gupta Oct 11 '12 at 13:10
  • Are you reserving the necessary space beforehand in destination char*? Accoding to reference (http://www.cplusplus.com/reference/clibrary/cstring/strcpy/): "To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source." – dunadar Oct 11 '12 at 13:11
  • 1
    We temporarily unable to read your mind due to technical difficulties. Show the code, please. – Rost Oct 11 '12 at 13:11
  • Any reasonable chance that FileIN is a dirty pointer that is either NULL or pointing to garbage? and the local strcpy from K to k isn't appearing to do much of anything. – WhozCraig Oct 11 '12 at 13:19
  • @WhozCraig: or points to a string longer than 59 bytes. – Steve Jessop Oct 11 '12 at 13:19
  • @SteveJessop Yessir. However, as written, a very lovely memory leak ensues, so methinks there is more wrong here than a misunderstanding of strcpy vs strncpy. – WhozCraig Oct 11 '12 at 13:20
  • 1
    @WhozCraig: true. btw, I never said "strncpy", neither would I advise using it. It's very unsafe ;-) – Steve Jessop Oct 11 '12 at 13:22
  • thanks gays for your answers, probably it is matter of pointer, like @Who and SteveJessop said – Oumaya Oct 11 '12 at 13:26
  • @SteveJessop yeah, disagree there. if you know how to use it it works fine (knowing that it tail-fills terminators on under-copies and does NOT terminate on limited copies for example, and coding accordingly). On the other hand, strncat is the one i find totally worthless. what fiend came up with that p.o.s ? – WhozCraig Oct 11 '12 at 13:26
  • @WhozCraig: `strcpy` works fine *if you know how to use it*. As does `memcpy`. My objection to `strncpy` is that it was designed for a particular purpose, nobody uses it for that purpose, it's not "safe" for the purpose they do use it, and because they're using it they aren't looking for / writing something like `strlcpy` and `strlcat`. So it's a pretty much total disaster. Especially in C++ :-) – Steve Jessop Oct 11 '12 at 13:33
  • @SteveJessop I can't argue with logic that rampant misuse of a lib routine hasn't made its *existence* a disaster. I, however, find it a more-telling statement of the masses incorrectly using the routine than the routine itself. You're correct that it has ben a complete disaster, but to this day I am shocked at how many *seasoned* engineers don't *know how it works*. – WhozCraig Oct 11 '12 at 13:43
  • @WhozCraig: I should probably have said, my objection to *using* `strncpy`. I'm pretty much indifferent to the function itself existing. You're right, the problem is people using it without properly understanding it, because someone told them in their formative years that it's "the safe way to copy strings". So they write code that fails to nul-terminate and/or truncates strings without detecting that this is almost always an error. – Steve Jessop Oct 11 '12 at 13:49
  • @SteveJessop yeah, I kinda figured that was what you really meant, and I couldn't agree with you more. Makes you wonder if any of the people that just read this exchange have since-poured over the strncpy docs to see if *they* really understand how it works (which would not be a bad thing) lol. Thanks Steve. – WhozCraig Oct 11 '12 at 13:54
  • 1
    Just in case they have, example of a "safe" way to use `strncpy`: `buf[len-1] = 0; strncpy(buf, src, len); if (buf[len] != 0) report_error;`. It is potentially more efficient than the same thing using `strlen` to check the length followed by `memcpy`, but then again it's also potentially less efficient, especially when `src` is significantly shorter than `len`. With `strlcpy` it would be `if (strlcpy(dst, src, len) >= len) report_error;`, which starts to look to me like the function "is safe" rather than "can be used safely". – Steve Jessop Oct 11 '12 at 13:57

4 Answers4

4

Short answer: You shouldn't use strcpy at all, but rather strncpy. The latter function does not rely on a trailing \0 and requires you to provide a maximum length for copying.

Furthermore, for pointer assignment you do not necessarily need strncpy at all. Do you want to copy the memory or simply reassign the pointers? For reassignment, the = operator is perfectly fine.

Gnosophilon
  • 1,340
  • 7
  • 24
  • Perhaps a useful comment, but not at all a correct answer. It does nothing to answer when you should use pointer assignment instead of any library function. –  Oct 11 '12 at 13:12
  • Yes, I was just going to clarify this. – Gnosophilon Oct 11 '12 at 13:13
  • I totally +1 this, but @Gnosophilon, at what point is a strncpy *unneccessarily* needed when simply assigning a char* to another char*? =) In my world, never =) – WhozCraig Oct 11 '12 at 13:27
4
const char *a = "string literal";
const char *b;

a is a pointer that points to a string literal. b is a pointer that doesn't point anywhere in particular (it is uninitialized).

b = a;

b now points to the same memory that a points to.

char c[100];

c is now an array of 100 chars. That area of memory is completely separate from everything else so far.

strcpy(c, a);

The contents of c (to be specific, the first 15 bytes) now hold the same values as the memory pointed to by a. So now there are two regions of memory that contain the same string data.

So as you can see, assigning pointers has pretty much nothing in common with strcpy. If you want to assign a char* to a char*, then you shouldn't be anywhere near strcpy.

It's essential that you read a book about C++, but the basic requirement for strcpy is that the destination pointer must point to a region of memory with enough space for the string that the source pointer points to. Probably your "run time memory problems" were because you didn't ensure that, which is why you need to read a book.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • thank you for this explanation, the difference between assigning pointers and strcpy is clear for me but my question was about issues with using strcpy and how can I a void it :) – Oumaya Oct 11 '12 at 13:34
  • @oumaya: it's not possible to say exactly what the problem is in the limited code you've shown. But the answer is what I say at the end, you have to get enough space from *somewhere*. There's more than one way to do that. – Steve Jessop Oct 11 '12 at 13:37
  • yeah, my point is calling this function for each file in a directory tree recursively for its sub directories, so I think and as you mentioned it is all about having a valid pointer and enough space in memory :) – Oumaya Oct 11 '12 at 13:45
2

char* is a pointer to the character of your string. To make a copy, you need to first allocate memory for it and the run the copy. Something like

size_t l = strlen(src);
char *dst = malloc(l+1);
memmove(dst,src,l+1);

(and do some error checking if malloc succeeded, etc).

Though, taking into account your question is tagged c++, I'd recommend that you use a std::string class and do some reading meanwhile. It really helps to understand how things actually work.

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
1

You need to make sure that the receiving buffer is large enough to fit the source string, including the terminating '\0'-character at the end. That's really it.

If you can represent strings as just char * pointers that you can copy, then that's great but it's not always possible.

unwind
  • 391,730
  • 64
  • 469
  • 606