0

I tried to print out the return value of strcpy() and it gave me an "Access violation reading location" exception.

char ind[15]; 
printf("%s\n", strcpy(ind, "source text"));

or with debugging statements:

char* ins = "source text";
char* dst;
dst = strcpy(ind, ins);
printf("dst = %s", dst);

Visual Studio showed that ind = 0x00000024ec71f448 "source text" whereas dst = 0xffffffffec71f448 <Error reading characters of string.> <Unable to read memory> .

Shouldn't dst = ind? pointing to the same address?

Great answers, all! Without <string.h>, it defaulted to "int strcpy()" when I hovered my mouse over strcpy. After including <string.h>, it showed "char *strcpy()".

About the address values, my PC runs a 64-bit Windows 10. Since "int" is typically 32 bit on most 64 bit platforms, dst is capped at 32-bit with bogus upper 32-bit.

One catch is that in order to use Visual Studio to build, you have to add #define _CRT_SECURE_NO_WARNINGS above all #include .h's to avoid compiler errors. The reason is that VS recommends using errno_t strcpy_s(...) instead of strcpy(). But strcpy_s() will then return a value of if successful. That makes our dst = 0, a NULL pointer, and the #define helps get around it.

After all the fixes, dst = ind = 0x000000249d8ff528 "source test". Thanks.

Leon Chang
  • 669
  • 8
  • 12
  • Well, is there a problem if you try using `ind` instead for the `printf` call? What happens if you compare `dst` and `ind` for equality? – Karl Knechtel Jul 02 '22 at 20:26
  • It looks as though the `dst` pointer you are seeing has the lower 32 bits correct and the upper 32 bits masked. Maybe something went wrong with selecting 64- vs 32- bit builds and linking the program? – Karl Knechtel Jul 02 '22 at 20:27
  • 1
    Questions seeking debugging help should generally provide a [mre] of the problem, which includes a function `main` and all `#include` directives. This allows other people to easily test your program, by simply using copy&paste. – Andreas Wenzel Jul 02 '22 at 20:31
  • Did you compile a debug build or a release build? If you are debugging a release build, then compiler optimizations may be interfering with the mapping of code lines to the program's instructions, so your debugger may be giving you misleading information. – Andreas Wenzel Jul 02 '22 at 20:34

1 Answers1

7

This can happen if you fail to #include <string.h>

Without a declaration for strcpy, the compiler uses an implicit declaration of int strcpy(). This is incompatible with the actual return type. Calling a function through an incompatible type triggers undefined behavior.

In this particular case, an int is smaller than a char *. This is why the return value of the function appears truncated in the debugger. The result is an invalid pointer value, and when you attempt to dereference that invalid pointer you read an invalid memory page triggering a crash.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • If an implicit declaration is indeed the reason for the problem, then OP should have received a warning message. At least the compilers gcc and clang both emit a warning message, even on default settings. – Andreas Wenzel Jul 02 '22 at 20:49
  • @AndreasWenzel Yes, MSVC 2015 gives a warning with the default settings. – dbush Jul 02 '22 at 20:51