Passing #define to a void * function - c

Im trying to pass a #define macro to a function that take a void* argument.
But I'm getting some segmentation fault so i think i did something wrong ;x.
And i cant understand what I'm doing wrong.
Here is the simple code i made to understand the problem :
#include <stdio.h>
#include <stdlib.h>
#define TEST 0xFFFFu
void f(void *test)
{
printf("%d\n", *(int*)test);
}
int main()
{
int b = 5;
f((int*)TEST);
return 0;
}
Thanks you.

The segmentation fault probably isn't related to the use of #define. You call the function with 0xFFFFu, which is an address your program probably doesn't own, and when you try to dereference it with the * operator you go out of the segment, and get a segmentation fault.

This code is valid as far as the C language goes. Please note that "passing a #define" is nonsense, a #define is just a pre-processor keyword which expands to an integer constant in this case.
So what your code actually does is to convert an integer constant 0xFFFF to a pointer, then attempt to de-reference that pointer to access address 0xFFFF.
We may cast from integers to pointers or the other way around, but this might cause misaligned access or instruction traps on some systems. And of course the address must be valid. Apparently your particular system is not amused by an int value access from address 0xFFFF and beyond.

Related

The "%p" printf parameter

I have this code:
#include <stdio.h>
#include <string.h>
void main(){
printf("%p");
}
This is the output:
0x7ffdd9b973d8
I know %p stands for pointer and when using it as for example
#include <stdio.h>
#include <string.h>
void main(){
int i = 0;
printf("%p", i);
}
it returns the pointer address of i. But my question is what does it return when not adding any other argument in the printf function just printf("%p")
Trash. printf uses a variable-length argument list. It uses the format string to determine how many arguments you actually passed. If you did not actually pass anything in, it will still read from basically arbitrary portions of memory as though you did. The result is undefined/trash.
Some compilers will be able to catch this situation with a warning because the printf family of functions is so popular. Some cases may crash your system if the function tries to read from memory you do not have access to. There is no way to tell how it will behave next time even if you have obtained a certain result.
But my question is what does it return when not adding any other argument in the printf function just printf("%p");
Anything. Nothing. Random junk. Maybe it crashes.
There is no way to know without investigating a specific combination of compiler, CPU, platform, libraries, execution environment, and so on. There is no rule that requires it to operate any particular way.
The behavior of
printf("%p");
is undefined. When you specify a %p format in the format string, the corresponding argument of void * (or char *) type shall be present in the argument list.

C Segmentation Fault within Kali Linux VM

I am trying to create a C program in a Linux VM that uses a char array. I found that every time I try to do anything to the array, e.g. sizeof(), I get a segmentation fault. I wrote a test program that just made an array and got sizeof() as a test, and sure enough I get the same error.
I think this is related to the program running in a VM. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define ARR_LENGTH(x) sizeof(x) / sizeof(x[0])
int main()
{
printf("Hllo world!\n");
int sent = 10;
char hello[] = {'a','b','c','d','e','f','g','h'};
printf(sizeof(hello));
printf(ARR_LENGTH(hello));
return 0;
}
Am I missing something, or is the VM likely the problem?
You just need to read the printf() documentation carefully. It doesn't take an integer as its first argument.
The problematic lines are:
printf(sizeof(hello));
printf(ARR_LENGTH(hello));
It should be:
printf("%zu\n", sizeof(hello));
printf("%zu\n", ARR_LENGTH(hello));
(%zu is the format specifier to print size_t values).
My gcc compiler produces the warning:
warning: passing argument 1 of ‘printf’ makes pointer from integer
without a cast [-Wint-conversion]
for those two statements. Up the compiler warning levels (in case you don't get them alrready).

ctime returns NULL randomly

I am using ctime. However it always returns NULL. So it cores on sprintf line. It worked earlier. So not sure why it is randomly returning NULL?
I have the following code snippet:
int main()
{
char avp_val[50];
uint32_t date_value=1477069401;
sprintf(avp_val,"%s",ctime((time_t*)(&date_value)));
return;
}
Don't cast a pointer to uint32_t to a time_t. Use an actual time_t, so on systems with 64 bit time_t ctime isn't reading four bytes of garbage as part of the epoch time:
int main()
{
char avp_val[50];
time_t date_value=1477069401;
sprintf(avp_val,"%s",ctime(&date_value));
// Or, because it's what you're doing anyway, skip sprintf:
// strcpy(avp_val, ctime(&date_value));
return 0;
}
Casting to (time_t*) to silence compiler warnings silenced the warnings, it didn't fix the problem.
Well, your code lacks a bunch of include files:
#include <stdlib.h> /* for the types you use below, like uint32_t */
#include <stdio.h> /* for a prototype for sprintf, which you use below */
#include <time.h> /* for a prototype for ctime() see NOTE 1 */
You must also take into account that casting must be done with data values, not with pointers, as casting a pointer only bypasses the compiler type checking system and makes your code more error prone. In this case you conversion from uint32_t * to time_t * is too dangerous if both types happen to have different sizes, as you'll be cutting the value using only half the bits required. This is something knows as Undefined Behaviour and you should avoid it.
You also have to return an explicit value from main. It's a compile error not to do so, so your example cannot execute, because it does not compile (and so, you cannot receive NULL from ctime(3))
By the way, I tried your code with uint32_t date_value in a mac OS/X and it printed the right value of time, so probably time_t is a 32 bit value, but you had better to use a time_t as it is defined by that reason.
NOTE 1
The most important in this case is the prototype of ctime(), which returns a pointer to char and without a prototype, the compiler assumes it returns an int. At least, in 64bit platforms, both types are different sizes, and cannot be passed this way.
Please, always post a Complete, minimum, verifiable example, as you can hide the exact source of the error by editing your example to be shown.

Error in the program to swap two numbers using Pointers

A few years back i was working with Turbo C compiler and the following code worked fine on it.
#include<stdio.h>
void main()
{
int a=2,b=3;
swap(a,b);
printf("%d\n%d\n",a,b);
}
swap(int *x,int *y)
{
int t;
//x=malloc(2);
//y=malloc(2);
t=*x;
*x=*y;
*y=t;
printf("%d\n%d\n",x,y);
}
Now i am working on cygwin and if i run this code i get an error Segmentation fault(core dumped)
If i uncomment the malloc statements i get the output
536937064
536937080
2
3
Are first two lines of output some garbage values? What exactly is happening here and how can i get the correct output?
Here is the corrected version of your program, which will execute correctly.
There are a number of things going wrong in the sample you posted:
Incorrect Argument type being passed:
swap(a,b);
should be :
swap(&a,&b);
Your function expects pointer to the integers to be modified, You are not doing so.
Incorrect Format specifiers for printf:
printf("%d\n%d\n",x,y);
should be:
printf("%d\n%d\n",*x,*y);
printf is not type safe and you need to ensure you use proper format specifiers while using it. Using incorrect format specifiers results in Undefined Behavior.
The next two are good practices if not errors and you should follow them.
Incorrect return type of main():
As per the Standard a program should return int,
void main()
should be
int main()
Also, add return a value return 0;at the end of main.
Function Declaration:
You should declare the function swap() correctly before main:
void swap(int *x,int *y);
Providing a function declaration before the place where you use it in code, gives the compiler a opportunity to match the parameters and report incorrect types being passed.
Further using malloc as you have would not acheive what you are trying to achieve, You do not need to use malloc here at all and One should always avoid using it as much as possible.
Also, You should pick up a good book and learn the basics.
Nothing here is actually correct.
The parameters to swap are the literal addresses 2 and 3. You can &a and &b in the call.
printf in swap is printing the pointer addresses, so the output is "expected".
If you were using malloc (why?), you are only allocating 2 bytes. An int is generally 4 , but please use sizeof.
You are passing values of the variables and using pointers to receive it.
`swap(a,b) `
should be swap(&a,&b)
because you must pass the address of the variables, not the variable itself. Read Call by reference in C.

Segmentation fault in C on Mac, direct copy from a tutorial

I've started learning C and pointers and I've been working on tutorials on the internet. I assume that the code should work as it is in a tutorial, and it seems right to me, but I get a segmentation error. The code is:
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
int main(int argc, char** argv) {
float fl = 3.14;
unsigned int addr = (unsigned int) &fl;
printf("fl's address=%u\n", addr);
printf("addr's contents = %.2f\n", * (float*) addr);
return (EXIT_SUCCESS);
}
The error that I get is
/Applications/NetBeans/NetBeans
6.9.1.app/Contents/Resources/NetBeans/ide/bin/nativeexecution/dorun.sh: line 33: 1626
Segmentation fault sh "${SHFILE}"
Does this have to do with me using a Mac or is there something wrong with the code?
Thanks a lot,
Niek
Try this instead:
int main(int argc, char** argv) {
float fl = 3.14;
float *addr = &fl;
printf("fl's address=%p\n", addr);
printf("addr's contents = %.2f\n", *addr);
return (EXIT_SUCCESS);
}
That may be undefined behaviour. There's no guarantee that an int and a pointer can hold the same value, and you should not be casting between them. Use a float* instead.
C99 6.3.2.3/5 and /6 state:
5: An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
6: Any pointer type may be converted to an integer type. Except as previously specified, the
result is implementation-defined. If the result cannot be represented in the integer type,
the behavior is undefined. The result need not be in the range of values of any integer
type.
Yes, the address space of pointer is not guaranteed to be the same as an int. In fact, this code gives me the following compilation warnings using gcc on a Mac Pro:
test.c:9: warning: cast from pointer to integer of different size
test.c:11: warning: cast to pointer from integer of different size
and a seg fault as well. I would consider samplebias' code.
The code seems to be correct, compiling with MinGW GCC and running gives the following output:
fl's address=2293528
addr's contents = 3.14
yes under win7 + mingw32, the code compiles\executes corrrectly
fl's address=2293572
addr's contents = 3.14
i think it's problem with MacOS only
The problem is the size of int. As #paxdiablo already said, there is no guarantee that an int is big enough to hold the same value as a pointer. Try long longinstead, but be warned, the code stays in the undefined behavior corner.

Resources