Home > OS >  Why Mingw64 exeption in <stdio.h> and not in my code?
Why Mingw64 exeption in <stdio.h> and not in my code?

Time:06-30

I am aware that the code I show below is incorrect, but I wonder why the stdio.h is blamed with:

appeared exeption in <stdio.h> script:

  __retval = __mingw_vfprintf( stdout, __format, __local_argv );

segmentation fault int stdout.

Code for beginners, actually:

#include <stdio.h>

int main()
{
printf(12345);
return 0;
}

I know that is might be incorrect, but i think, error should appeared in my file, but not in the script <stdio.h> file.

The main question for me, is why if i would call printf(Hello World), it won't show me the <stdio.h> error, but as for 12345 it shows? I started C language today, no practice, sorry)

CodePudding user response:

The problem is in your code of course:

printf(12345);

The first parameter of the printf function has to be a format string. In your case you pass the integer converted to pointer (it is very unlikely this pointer to reference the valid memory). printf function tries to derefence it and you get a segfault.

To print 12345 you need to:

printf("%d", 12345);

The main question for me, is why if i would call printf(Hello World), it won't show me the <stdio.h> error

printf("hello world"); is correct as the fist parameter is a valid C string.

CodePudding user response:

First of all, this code is not valid C. A correctly configured compiler (https://software.codidact.com/posts/282565) may simply refuse to generate a program, because of the "Pointer from integer/integer from pointer without a cast" issues.

Some compilers like gcc/mingw might allow implicit conversions from integer to pointers when you run them in lax, non-standard mode. 12345 is then treaded as the address value of the char* format string that printf expects.

As for why the code crashes in some stdio.h header, it first of all depends on how you execute the code - you'll have to run it in a debugger (mingw/gdb) to know where it crashed, or otherwise the OS will just say access violation (Windows) or seg fault (*nix).

When running this in mingw64/gdb, I can reproduce the crash as:

#2 0x00007ff7f4471817 in printf (__format=0x3039 <error: Cannot access memory at address 0x3039>) at c:/program files/mingw-w64/x86_64-w64-mingw32/include/stdio.h:372

It points at the printf function inside stdio.h which as it turns out is just a thin wrapper around an internal library function __mingw_vfprintf:

__retval = __mingw_vfprintf( stdout, __format, __local_argv );

This is as deep as my mingw64 lets me go in C code, likely the definition of this function sits in a static linked lib and there's no C code for it that I have access to.

As for the machine code, it crashes on this specific assembler instruction:

0x7ff7f44758e2  movzx  eax,BYTE PTR [rax]

This appears to happen during the stacking required by the __cdecl calling convention for the printf call. rax contains the magic number 0x3039 aka 12345 when this happens. Exactly what caused the MMU to freak out, I don't know, but we do know that 0x3039 is not a valid address (and misaligned at that). Some x86 assembler guru can perhaps explain why exactly this happened in this particular ISA... but this is already way too deep for the average C programmer to care.

  •  Tags:  
  • c
  • Related