-3

I am using strcpy on two char arrays with destination array smaller than the source array. But strcpy doesn't seem to care. In fact, it copies source array shamelessly to the destination array and I can even cout the new destination array.

#include <iostream>
#include <cstring>
int main(){
    char src_str[10] = {'D','e','s'};

    char dst_str[2] = {'S', 'r'};

    strcpy(dst_str, src_str); 
    std::cout << dst_str << std::endl;
    std::string stdstr(dst_str);
    std::cout << "stdstr: " << stdstr << std::endl;

    std::cin.ignore();
}

It prints;

Des

stdstr: Des

I am compiling with g++ (5.4.0) on Ubuntu.

Community
  • 1
  • 1
Manish Verma
  • 75
  • 1
  • 11
  • 2
    Why would it? Raw memory buffers don't know anything about size. Use classes that support bounds checking if it's important to you. – Mad Physicist Feb 28 '18 at 07:09
  • 7
    Undefined behavior is undefined. – Miles Budnek Feb 28 '18 at 07:09
  • It's undefined behavior. Trying to make sense of it is futile. – R Sahu Feb 28 '18 at 07:10
  • 1
    How would you go about writing a `strcpy` that does? – chris Feb 28 '18 at 07:11
  • 2
    Your program causes **undefined behavior**. Undefined means that the program can do anything, which includes the behavior you observe as well. – Daniel Langr Feb 28 '18 at 07:11
  • So if it is undefined then would it be okay if I consider what it allows me to do above is correct default behavior? And I can use it anywhere in my regular code? – Manish Verma Feb 28 '18 at 07:13
  • Why don't you use std:: string? – JVApen Feb 28 '18 at 07:16
  • I am simply trying to understand what is actually happening underneath. Of course, I can use std::string. – Manish Verma Feb 28 '18 at 07:17
  • 5
    @ManishVerma Never ever create code with undefined behavior. Such code is incorrect by all means and you cannot reason about its correctness by an effect observed in a single case. – Daniel Langr Feb 28 '18 at 07:17
  • 4
    @ManishVerma It makes no sense to _"try to understand what is actually happening"_ if undefined behavior is involved. – Daniel Langr Feb 28 '18 at 07:19
  • @DanielLangr Can you please elaborate on why it doesn't make sense if someone wants to understand as to how exactly a piece of code is being handled by the compiler, even if the behavior is undefined? – Manish Verma Feb 28 '18 at 07:24
  • 'What is actually happening' is described completely and accurately in the documentation. There is nothing left to understand. – user207421 Feb 28 '18 at 07:27
  • The question asked at https://stackoverflow.com/questions/1239938/accessing-an-array-out-of-bounds-gives-no-error-why and the chosen answer is the one I was looking for. Unfortunately, I couldn't find it before. Thanks. – Manish Verma Feb 28 '18 at 07:44
  • 1
    @EJP: The whole point of "Undefined Behavior" is that it is **not** described in the documentation. There is "implementation-defined behavior", like the range of `int`, which **is** documented completey. – MSalters Feb 28 '18 at 09:20
  • @MSalters Exactly my point. If it isn't described, it isn't defined, so OP cannot rely on it. I am trying to get him to do that investigation for himself and find that his suppositions are baseless. – user207421 Feb 28 '18 at 09:36
  • @ManishVerma If you want to understand what happes in your particular case, draw your stack bytes. On x86 architecture, stack "grows" to lower addresses, so `dst` array is placed on lower address than `src` array. Note also, that `src` should be null-terminated; simply append `'\0'` character. Try to print `src` after `strcpy`, it should contain null-terminated `"s"` string. (I deleted my previous comment, since it would be true only for stack that would grow to higher addresses). – Daniel Langr Feb 28 '18 at 09:59

1 Answers1

1

How could it? It doesn't know. strcpy() doesn't have any error checking for the length. It can't, because all you pass to strcpy() is two pointers and no length information at all.

strcpy() just starts at the address of the first element copying byte to byte each element and stops when it has copied a zero.

user207421
  • 305,947
  • 44
  • 307
  • 483
Fanto
  • 128
  • 1
  • 9
  • Stops when it finds 0 in the destination, right? – Manish Verma Feb 28 '18 at 07:15
  • @ManishVerma a) there is no 0 in your destination array. b) no, `strcpy` does not check for 0 in the destination (people often zero out their buffers before writing to them, so that wouldn't work). – Miles Budnek Feb 28 '18 at 07:17
  • @ManishVerma No, where does it say that? – user207421 Feb 28 '18 at 07:20
  • Fanto said that, I was simply confirming. – Manish Verma Feb 28 '18 at 07:21
  • @ManishVerma No he didn't, and neither does the documentation. Have you considered reading it? – user207421 Feb 28 '18 at 07:22
  • 1
    @ManishVerma It stops *if* it finds a zero in the *source*. – Bob__ Feb 28 '18 at 07:23
  • @Bob__ that is not what is happening. It doesn't stop at the terminating zero of the source. It keeps writing beyond that up to the end of the source. – Manish Verma Feb 28 '18 at 07:29
  • 1
    @ManishVerma There *is* no terminating zero in your source. It is a char array, not a null-terminated string. It keeps copying until it *does* find a null. That's the *problem.* – user207421 Feb 28 '18 at 07:33
  • @EJP I guess there must be some zero character in the source array, otherwise, copying of characters would never end (due to overlapping arrays) until some segmentation fault due to invalid memory access. – Daniel Langr Feb 28 '18 at 07:38
  • 1
    @EJP That is not the case, just checked that. – Manish Verma Feb 28 '18 at 07:39
  • 1
    @ManishVerma read the documentation of `strcpy` all the information you need is _there_. Period. – Jabberwocky Feb 28 '18 at 07:48
  • 1
    @ManishVerma *What* is not the case? Where in the C++ language specification does it define the trailing contents of an under-initialized array? You need to stop guessing and start reading. – user207421 Feb 28 '18 at 07:51
  • @DanielLangr *Non sequitur.* There is certainly a null somewhere, but where it is is not defined anywhere. – user207421 Feb 28 '18 at 07:52