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).
Related
#include <stdio.h>
#include <stdlib.h>
void main (){
char* shell = getenv("MYSHELL");
if (shell)
printf("%x\n", (unsigned int)shell);
}
shell.c: In function ‘main’:
shell.c:7:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
7 | printf("%x\n", (unsigned int)shell);
First of all, that's a warning, not an error. The compiler will still allow you to compile your program when it has warnings (though many programmers would advise fixing those warnings), but if you get a compiler error your code will not compile at all.
The reason for the warning is that char* is a pointer type, which on x64 architectures is essentially a 64-bit integer. int, and by extension unsigned int, is a 32-bit integer. If you want to silence the error, you could cast to unsigned long instead (and change the %x to %lx), but there's a much easier way. There is a format specifier for pointers, %p, which you can simply use with any pointer.
So if you want to silence the warning I'd recommend changing your print statement to printf("%p\n", shell);
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.
This question already has answers here:
Message "warning: implicit declaration of function"
(10 answers)
Closed 6 years ago.
I have this very simple code written in C. They are in two separate files.
myFunction.c
#include <stdlib.h>
int *extFunc() {
int *a = (int *) calloc( 1, sizeof(int) );
*a = 12;
return a;
}
main.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int *) extFunc();
int x = *p; // causes segmentation fault !
printf("%d\n", *p); // causes segmentation fault !
}
I compiled it with this command cc myFunction.c main.c and the output is like below
main.c:6:19: warning: implicit declaration of function 'extFunc' is invalid in C99 [-Wimplicit-function-declaration]
int *p = (int *) extFunc();
^
main.c:6:11: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]
int *p = (int *) extFunc();
^
2 warnings generated.
and when I run it, it gives Segmentation fault: 11. What am I doing wrong?
I checked the function when it is in the main.c file and it worked. However, I need them to be separate like above.
In my original code there are struct pointers instead of integer pointers. I explained my problem here with a simplified example.
You haven't provided a prototype for extFunc(). Create a header file with:
int *extFunc(void);
and include it in both source files.
Since the compiler can't see a prototype it assumed int as return type for extFunc() which probably truncates the address returned by calloc() on your system (probably 64bit system).
But there's no implicit int rule since C99. Always include prototypes for functions and pay attention to compiler warnings.
The warnings are very important here. Especially the one saying
cast to 'int *' from smaller integer type 'int'
What is happening is that the compiler makes an implicit declaration of the function. One that doesn't return int * but int. On certain platform (most notably 64-bit systems) those are not the same which means the pointer p in your main function is not correct. Dereferencing it will lead to undefined behavior.
You need to add a declaration of your function for it to work:
int *extFunc(void);
int main(void) { ... }
Also note that I have changed the argument type for both your extFunc and for main. This is because in C when you don't explicitly say that a function takes void as argument then it can take any number of unspecified arguments.
Compiling both files is not enough, you need to create a header:
/* myFunction.h */
int *extFunc();
And then, include it in your main file:
#include <stdio.h>
#include <stdlib.h>
#include "myFunction.h" /* here */
int main()
{
...
}
The main cannot see the declaration of the function extFunc, so it's return type default to int.
As types int and int* are not of the same size, the function returns an invalid pointer, which when dereferenced caused a segmentation fault.
You will need to create a header called myFunction.h, which will contain the declaration of the function:
int* extFunc( void );
Include this header in main and also change the definition of extFunc to take no arguments in myFunction.c.
I am trying to compile the following simple code in Workbench:
1. typedef float matrixType[3][3]
2.
3. void my_func(matrixType matrix)
4. {
5. printf("matrix[0][0] = %g\n",matrix[0][0]);
6. }
7.
8. void main()
9. {
10. matrixType my_matrix = {{0,1,2},{3,4,5},{6,7,8}};
11. matrixType* ptr_matrix = &my_matrix;
12.
13. my_func(*ptr_matrix);
14. }
I receive the following warning:
test.c:13: warning: passing arg 1 of `my_func' from incompatible pointer type
I can't understand, what am I doing wrong. The compilation of the same code in Visual Studio works without any warnings, but in Workbench something is going wrong.
Thanks.
With gcc (GCC) 4.5.3 with all warnings turned on it also compiles fine after making the following changes:
Add a semicolon after the first line.
Add #include <stdio.h> at top.
Change the return type of main to int.
Add return 0; as the last line.
The void main() is not correct C even though it appears in various books, manuals, and web tutorials. On some architectures it will cause strange problems, usually as the program terminates.
Taking the address of an array type is challenging the workbench type checker. I'm not going to drag out the C standard to figure out if the workbench warning is correct. It's probably a bug.
But I'm pretty sure that if you recode this way you will see no errors with any compiler:
#include <stdio.h>
typedef float rowType[3];
typedef rowType matrixType[3];
void my_func(matrixType matrix)
{
printf("matrix[0][0] = %g\n",matrix[0][0]);
}
int main()
{
matrixType my_matrix = {{0,1,2},{3,4,5},{6,7,8}};
rowType* ptr_matrix = my_matrix;
my_func(ptr_matrix);
return 0;
}
The reason is that my_matrix is automatically converted to a pointer to it's first element in the assignment
rowType* ptr_matrix = my_matrix;
This is just as in
char s[] = "hello world!";
char *p = s;
the array name s is converted to a pointer to its first element.
The parameter in void my_func(matrixType matrix) has a type identical to rowType* because all arrays are also passed as pointers to first elements. So all the types in this code must match in a way that's very clearly defined in the C standard. &my_matrix may not be incorrect, but it's an "edge case" more likely to expose type checking bugs.
You are missing a semicolon at the end of line 1.
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.