Why Mingw64 exeption in <stdio.h> and not in my code? - c

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)

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.

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.

Related

secure_getenv function not giving the expected result

In my program I am using secure_getenv function to fetch some environment variables. I included stdlib.h in my program. This is the sample call to secure_getenv.
Line 1 : char *myenv;
Line 2 : myenv = __secure_getenv("DATA");
After the above lines execution, myenv points to some junk.
I tried this within gdb after line 2.
p __secure_getenv("DATA")
This prints me the DATA I wanted.
But when I try,
"p myenv",
It prints the below.
$2 = 0×fffffffffffffe13f<Address 0xfffffffffffffe13f out of bounds>"
Can the experts help me to understand what is missing & how to make this work.
Edited to add:
How the myenv is actually used?
In somepoint in time my code tries to call the below.
strlen(myenv);
On strlen function call, my code terminates with sig11(SIGSEGV)
Can the experts help me to understand what is missing & how to make this work.
The most likely cause is that you don't have a prototype for __secure_getenv, which means that the compiler assumes that this function returns an int. That int is then cast to char*, which sign-extends it to produce "garbage" pointer 0xfffffffffffffe13f.
You should compile your source with -Wall -Wextra -- the compiler will then warn you about the bug.
You should #include <stdlib.h> and use secure_getenv() instead of __secure_getenv() -- the former will have a proper prototype.
You can compare the output from p __secure_getenv("DATA") -- it will print the data you expect, and also the pointer value. If my guess is correct, the pointer value will have different high-order bits, but same low 32-bits as myenv == 0xfffffffffffffe13f

How to use printf() without any libraries in C?

I am programming a Teensy micro-controller as a part of a C course and am trying to work out the value of one of my integer variables. I have an integer variable called Contrast, which is initialised to the value of a constant defined as a hexadecimal number at the beginning of the .c file:
#define LCD_DEFAULT_CONTRAST 0x3F
int Contrast = LCD_DEFAULT_CONTRAST;
I am trying to investigate how this Contrast value is stored and displayed, if it shows up as 63 or 0x3F, and if they are interchangeable. I tried to use:
printf("%d", Contrast);
to print out the Contrast value to the terminal and I got the error implicit declaration of function 'printf'. I thought printf() was part of the built-in C library, so I am confused why this is not working.
Can anyone please tell me how I print the value of this variable to the screen?
The implicit declaration error just means your compiler proper doesn't have a declaration for printf. Unless you're also getting a linker error, the linker (linking usually follows compilation, unless you pass -c to disable it) is probably slapping the standard lib right on, in which case you can simply solve your warning by including stdio.h or less preferably by declaring int printf(char const*, ...);.
If you trully don't have the standard lib, you'll need to convert the integer to a string manually with something like:
int n = 42;
char buf[20];
char *end = buf+(sizeof(buf)-1), *p = end;
*p--=0;
if(n==0) *p=='0';
else{
while(n){
printf("%d\n", n%10);
*p--=n%10+'0';
n/=10;
}
p++;
}
and then pass it to your system's raw IO routine for which you'll need to have set up the system-entering assembly.
If you don't have a system, it'd be even more technical, and you probably wouldn't be asking this question.
printf() is declared in standard library header <stdio.h>.
You have to #include <stdio.h> to use printf(). It is a library call, much like all other library calls in C..

Why there is no error when passing command line arguments when declaring main as `int main(void)`?

Case 1:
void hello(void) {
//something
}
int main()
{
hello(1); //error
return 0;
}
Case 2:
int main(void) {
//something
return 0;
}
Execution:
./a.out something something //No error, Why?
Why there is no error? main will not be able to take any arguments. So why it is possible to provide arguments from the command line?
Because the C compiler and the command line interpreter (or whatever is used to invoke your program) are different things.
The C language allows various ways how main () could be declared.
The command line interpreter will make any arguments available to the program. If the program ignores them, that's none of its business.
The command line interpreter doesn't even know that you used C to compile your program. On my computer, the program could be written in C, C++, Objective-C, Objective-C++, Swift, Fortran, Ada, and so on. Each of these compilers may or may not do things to accept commands from the command line.
Not checking the specification nor compiled result, it will cause no error because the C runtime will get the arguments and pass them to main(), but this type of main() will ignore the passed arguments, and if it is caller's duty to clean up the memory (stack) used as the arguments, it will cause no problems just as getting some arguments and not using them in the code.
This code won't emit errors in C:
void hello(); // in C, the compiler won't check arguments
int main() {
hello(1); //no error
return 0;
}
void hello(void) {
//something
}
Because ./a.out something something is not directly calling your main function. THe main function is being called by the c runtime library. The command line arguments are placed in a region somewhere on the stack (very beginning) by the loader/c runtime. It is upto you if you want to access these arguments or not.
Plus as pointed out in one of the comments as well at least one command line argument is always passed anyways (the name of the program ./a.out to be precise) - so you must have wondered about an error in that case as well.
Recall that ISO C specifies the two possible signatures of main: int main(void) and int main(int, char *[]) and the equivalent versions thereof, like int main(int, char **) because of array-to-pointer decay. This is covered more in detail here.
This question can be answered by considering the opposite question: how does the C runtime know what main to call? C doesn't have overload resolution! This is explained here. Briefly, the others are pushed but not accessed because there's no indication from C to do that.
When you compile your program using gcc program_name.c, compiler will report any possible compile time warning or error. Since the command line arguments are not passed at the compile time, compiler is unaware of it and program just ignore that arguments.
In case of hello, compiler knows the prototype of this function and expects no argument to be passed in its call and hence reports error in case of any argument passed to it.

Why does this do whatever it does?

#include <stdio.h>
void littledot(){}//must use C, not C++
int main() {
littledot(568,76,105,84,116,76,101,68,111,84);
printf("%c%c%c%c%c%c%c%c%c\n");
getchar();
return 0;
}
The above code yields the result "LiTtLeDoT". Why does it do that? Why is 568 crucial?
This differs per platform and is UB (the implementation can do anything it wants*), but probably the arguments to littledot() are still on the stack after littledot() returns and printf prints those arguments from the stack.
NEVER RELY ON THIS!
*really anything. Afaik an ancient version of GCC started a videogame when it encountered something that would behave in an undefined way.
You were lucky. This is undefined behaviour, specifically the call to printf. The program could do anything. Your implementation happens to write "LiTtLeDoT".
The really is the nature of undefined behaviour. The compiler can do anything it wants. If you really want to know why it does what it does then you will need to look at the emitted object code. Looking at the C code will yield nothing because of the aforementioned undefined behaviour.
This is what's working reliably for me with Open Watcom 1.9 on Windows:
//must use C, not C++
#include <stdio.h>
#include <stdlib.h>
void
__stdcall // callee cleans up
littledot()
{
}
int main(void)
{
littledot(/*568,*/'L','i','T','t','L','e','D','o','T');
printf("%c%c%c%c%c%c%c%c%c\n");
getchar();
exit(0);
return 0;
}
littledot() is called with a number of parameters that are passed on the stack.
If the calling convention for littledot() is __stdcall (or __fastcall), it will have to remove its parameters from the stack.
If it's __cdecl, then main() will have to remove them, but this won't work for us.
However, littledot() doesn't and can't do anything about the parameters because they're not specified, which is something you can do in C, but not C++.
So, what happens is that not only littledot()'s parameters remain on the stack after the call to it, but also the stack pointer is not restored (because neither littledot() nor main() remove the parameters, which is typically done by adjusting the stack pointer) and the stack pointer points to 'L'. Then there's the call to printf() that first places on the stack the address of the format string "%c%c%c%c%c%c%c%c%c\n" thus forming all expected parameters for the function on the stack. printf() happily prints the text and returns.
After that the stack isn't correctly balanced and doing return in main() is risky as the app may crash. Returning by means of exit(0) fixes that.
As all others have said, none of this is guaranteed to work. It may only work with specific compilers for specific OSes and then only sometimes.
http://codepad.org/tfRLaCB5
I'm sorry, what you claim the program to print is not what happens on my box and not what happens on codepad's box.
And the reason is, the program has undefined behavior. printf expects one additional argument (an int) for every %c you have in the format string. You don't give it those arguments, hence anything can happen.
You are in a situation where with certain implementations of printf, compiler options, certain compilers and certain ABIs, you end up with that output. But you should not think that this output is required by any specification.

C programming language, array, pointer

int main()
{
int j=97;
char arr[4]="Abc";
printf(arr,j);
getch();
return 0;
}
this code gives me a stack overflow error why?
But if instead of printf(arr,j) we use printf(arr) then it prints Abc.
please tell me how printf works , means 1st argument is const char* type so how arr is
treated by compiler.
sorry! above code is right it doesn't give any error,I write this by mistake. but below code give stack overflow error.
#include <stdio.h>
int main()
{
int i, a[i];
getch();
return 0;
}
since variable i take any garbage value so that will be the size of the array
so why this code give this error when i use DEV C++ and if I use TURBO C++ 3.0 then
error:constant expression required displayed. if size of array can't be variable then when
we take size of array through user input.no error is displayed. but why in this case.
please tell me how printf works
First of all, pass only non-user supplied or validated strings to the first argument of printf()!
printf() accepts a variable number of arguments after the required const char* argument (because printf() is what's called a variadic function). The first const char* argument is where you pass a format string so that printf() knows how to display the rest of your arguments.
If the arr character array contains user-inputted values, then it may cause a segfault if the string happens to contain those formatting placeholders, so the format string should always be a hard-coded constant (or validated) string. Your code sample is simple enough to see that it's really a constant, but it's still good practice to get used to printf("%s", arr) to display strings instead of passing them directly to the first argument (unless you absolutely have to of course).
That being said, you use the formatting placeholders (those that start with %) to format the output. If you want to display:
Abc 97
Then your call to printf() should be:
printf("%s %d", arr, j);
The %s tells printf() that the second argument should be interpreted as a pointer to a null-terminated string. The %d tells printf() that the third argument should be interpreted as a signed decimal.
this code gives me a stack overflow error why?
See AndreyT's answer.
I see that now the OP changed the description of the behavior to something totally different, so my explanation no longer applies to his code. Nevertheless, the points I made about variadic functions still stand.
This code results in stack invalidation (or something similar) because you failed to declare function printf. printf is a so called variadic function, it takes variable number of arguments. In C language it has [almost] always been mandatory to declare variadic functions before calling them. The practical reason for this requirement is that variadic functions might (and often will) require some special approach for argument passing. It is often called a calling convention. If you forget to declare a variadic function before calling it, a pre-C99 compiler will assume that it is an ordinary non-variadic function and call it as an ordinary function. I.e. it will use a wrong calling convention, which in turn will lead to stack invalidation. This all depends on the implementation: some might even appear to "work" fine, some will crash. But in any case you absolutely have to declare variadic functions before calling them.
In this case you should include <stdio.h> before calling printf. Header file <stdio.h> is a standard header that contains the declaration of printf. You forgot to do it; hence the error (most likely). There's no way to be 100% sure, since it depends on the implementation.
Otherwise, your code is valid. The code is weird, since you are passing j to printf without supplying a format specifier for it, but it is not an error - printf simply ignores extra variadic arguments. Your code should print Abc in any case. Add #include <stdio.h> at the beginning of your code, and it should work fine, assuming it does what you wanted it to do.
Again, this code
#include <stdio.h>
int main()
{
int j=97;
char arr[4]="Abc";
printf(arr,j);
return 0;
}
is a strange, but perfectly valid C program with a perfectly defined output (adding \n at the end of the output would be a good idea though).
In your line int i, a[i]; in the corrected sample of broken code, a is a variable-length array of i elements, but i is uninitialized. Thus your program has undefined behavior.
You see strings in C language are treated as char* and printf function can print a string directly. For printing strings using this function you should use such code:
printf("%s", arr);
%s tells the function that the first variable will be char*.
If you want to print both arr and j you should define the format first:
printf("%s%d", arr, j);
%d tells the function that the second variable will be int
I suspect the printf() issue is a red herring, since with a null-terminated "Abc" will ignore other arguments.
Have you debugged your program? If not can you be sure the fault isn't in getch()?
I cannot duplicate your issue but then I commented out the getch() for simplicity.
BTW, why did you not use fgetc() or getchar()? Are you intending to use curses in a larger program?
===== Added after your edit =====
Okay, not a red herring, just a mistake by the OP.
C++ does allow allocating an array with the size specified by a variable; you've essentially done this with random (garbage) size and overflowed the stack, as you deduced. When you compile with C++ you are typically no longer compiling C and the rules change (depending on the particular compiler).
That said, I don't understand your question - you need to be a lot more clear with "when we take size of array through user input" ...

Resources