I am trying the following, with gcc on win32.
#include <stdio.h>
struct st { char c; int x; } __attribute__ ((packed));
int main() {
printf("%d\n", sizeof(struct st));
return 0;
}
I would expect that the printed value is 5, but it's 8.
With the following, however, I get 5.
#include <stdio.h>
#pragma pack(1)
struct st { char c; int x; };
int main() {
printf("%d\n", sizeof(struct st));
return 0;
}
There must be something wrong in my program, but I can't see what.
I have read gcc's manual and several questions on SO about this, and I'm still puzzled. Any hint?
Also from the answers to these questions on SO, I understand that I should not use packed structs for marshalling, and I probably won't use it much, but I still would like to understand what I'm not able to see in such a short program.
Note: the problem occurs with both gcc-4.9.2 and gcc-4.8.4.
You have the attribute in the wrong place - try this:
struct st { char c;
int x __attribute__ ((packed));
};
As per the example in the gcc manual, this will cause x to be packed such that it immediately follows c.
Of course you shouldn't really be doing this in the first place, as your code will break on certain architectures, and even where it doesn't break there may be performance penalties.
Working fine on my environment Centos 5.11 (64bit)
prints 5 for the first case you mentioned.
gcc version 4.9.1 (GCC)
gcc file.c
./a.out
5
Related
As far as I've understood this far array[1] and array+1 are practically two ways of writing the same thing. However I've been looking at void pointers and arrays recently and made this program to test my understanding of it.
#include <stdio.h>
#include <stdlib.h>
int main(void){
void** data;
data = malloc(sizeof(int)*2);
*((int*)data) = 5;
*((int*)(data+1)) = 10;
printf("%d\n", *((int*)data));
printf("%d\n", *((int*)(data+1)));
free(data);
return 0;
}
That is the version of the program that works, for some reason however this version doesn't
#include <stdio.h>
#include <stdlib.h>
int main(void){
void** data;
data = malloc(sizeof(int)*2);
*((int*)data[0]) = 5;
*((int*)data[1]) = 10;
printf("%d\n", *((int*)data));
printf("%d\n", *((int*)data1]));
free(data);
return 0;
}
I'm not exactly getting compiler errors but program simply stops running, I've compiled this on a win 10 machine using gcc with the following flags -pedantic-errors -Wall and like i said before, the program compiles but when run I get the classic Program.exe has stopped working error message and so far I really can't think of a single reason why one of those would work and the other wouldn't.
data+1 is not valid C. You cannot do pointer arithmetic on void pointers, since that wouldn't make any sense.
So it would seem that you are using gcc in non-standard crap mode (default setting), which translates void pointer arithmetic to character arithmetic and therefore the program compiles, but as non-standard C. data+1 would then mean +1 byte, not +1 int.
Use gcc as a a standard C compiler instead -std=c11 -pedantic-errors. Then change the code to (int*)data+1.
Also the void** makes no sense, should be a void*. Please note that (int*)data[0] means "do pointer arithmetic on void** type, then cast the result to int*. This is an operator precedence bug. [] has higher precedence than the cast () operator.
Just toss that whole code out and use this:
#include <stdio.h>
#include <stdlib.h>
int main(void){
void* data;
data = malloc( sizeof(int[2]) );
((int*)data)[0] = 5;
((int*)data)[1] = 10;
printf("%d\n", *(int*)data );
printf("%d\n", *((int*)data+1) );
free(data);
return 0;
}
Both your examples are not correct.
void** data = malloc(sizeof(int)*2);
is allocating 2 int integers, but data if of type void**.If you wish to still use this, which is not recommended, you need to allocate 2 void* pointers. This would then be:
void** data = malloc(sizeof(void*)*2);
Having said this, using void** is not needed here. You can just use void* as pointed out in #Lundin's post. Your code would be optimal if you use int *data instead though, as it doesn't really make sense to use void* pointers here. If you decide to do this, your code can just be:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int *data;
data = malloc(sizeof(int)*2);
data[0] = 5;
data[1] = 10;
printf("%d\n", data[0]);
printf("%d\n", data[1]);
free(data);
return 0;
}
Which is more straightforward, and skips the complications that void* pointers bring in code.
Note: You must check return of malloc() always, as it can return NULL on failure.
first: please change the type of data to int* or at least to void*.
don't mess with void** unless you need to pass to a function a pointer.
second: change data[0/1] to &data[0/1].data[] is an argument and &data[] is his pointer. if you still using the void* choose *((int*)data+?). if yopu changed to int* use data[?].
third: why to use pointers in this function? this is not a function that need pointers.
fourth: i would suggest in this case to use an array instead of the pointers. if you already know the type and size of your argument so you better use arrays. more comfortable.
As it is said that 8 mb of stack is given to each process.
This stack will be used to store local variables.
So if i take an array of size max than of the stack , it must overflow ??
int main()
{
int arr[88388608];
int arr1[88388608];
int arr2[88388608];
while(1);
return 0;
}
But i am unable to get the result !
Welcome to the world of optimizing compilers!
Because of the as-if rule, the compiler is only required to build something that would have same observable results as your original code.
So the compiler if free to:
remove the unused arrays
remove the empty loop
store the dynamic arrays from main outside of the stack - because main is a special function that shall be called only once by the environment
If you want to observe the stack overflow (the bad one, not our nice site :-) ),
you should:
use some code to fill the arrays
compile with all optimization removed and preferently in debug mode to tell the compiler do what I wrote as accurately as you can
The following code does SIGSEGV with CLang 3.4.1 when compiled as cc -g foo.c -o foo
#include <stdio.h>
#define SIZE 88388608
void fill(int *arr, size_t size, int val) {
for (size_t i=0; i<size; i++) {
arr[i] = val;
}
}
int main() {
int arr[SIZE];
int arr1[SIZE];
int arr2[SIZE];
fill(arr, SIZE, 0);
fill(arr1, SIZE, 0);
fill(arr2, SIZE, 0);
printf("%d %d %d\n", arr[12], arr1[15], arr2[18]);
return 0;
}
and even this code works fine when compiled as -O2 optimization level... Compilers are now too clever for me, and I'm not brave enough to thoroughly look at the assembly code which would be the only real way to understand what is actually executed!
I want to be able to reference variable sized array with a global pointer. But what kind of pointer do I use that will work with variable sizes of the array? In the example below, assume N will only be known at runtime (could be an argument for example) so compile time solutions won't work.
What I want to achieve:
main.c
some_sort_of_pointer *x;
main()
{
int N=256; //or N=64 or whatever
char (*LC)[N];
LC=malloc(1024);
x=LC;
memcpy(x[2],"hello world",11);
x[0][176]=123;
dostuff();
}
I'm sure there's an easy obvious way to do this but I can't seem to nail it. My first attempt at asking this was a mess so this time I'm hoping it's clear what I want to achieve.
OS Centos 6.5
compiler GCC 4.8 (using C99)
As at compile time the type to be referenced isn't given, a void pointer might help.
However only storing an untyped reference (what void * in fact is is) is not enough, as it is essential to also know the size of the (VL)array. So the latter also needs to be stored globally, as it can not be pulled from the memory referenced.
An example how this can be achieve is given below:
main.h:
#include <stdlib.h> /* for size_t */
struct VLA_descriptor
{
void * p;
size_t s;
}
extern struct VLA_descriptor vla_descriptor;
foo.h:
void foo(void);
foo.c:
#include "main.h"
#include "foo.h
void foo(void)
{
char (*p)[vla_descriptor.s] = vla_descriptor.p;
/* Do something with the VLA reference p. */
}
main.c:
#include "main.h"
#include "foo.h"
struct VLA_descriptor vla_descriptor = {0};
int main(int argc, char ** argv)
{
size_t s = atoi(argv[1]);
char (*p)[s] = malloc(s);
vla_descriptor.p = p;
vla_descriptor.s = s;
foo();
... /* Free stuff and return. */
}
Error checking had been omitted in this example's code for the sake of readability.
With much thanks to #alk (and everyone else who responded) I think I have the closest I'm going to get to what I'm looking for:
void *LC
int LCS;
int main(int argc, char **argv) {
LCS=256;
LC=malloc(1024)
memcpy(((char(*)[LCS])LC)[2],"hello world",11);
((char(*)[LCS])LC)[0][176]=123;
printf("%d %s\n",((char(*)[LCS])LC)[0][176],&((char(*)[LCS])LC)[2]);
}
((char(*)[LCS])LC) is the equivalent of a what I wanted. It's similar to #alk's idea and does require 2 globals but it means I can use it in functions without having to declare a new variable. I've credited #alk with the answer as what he posted gave me 90% of what I needed.
Though if anyone can reduce ((char(*)[LCS])LC) to a single global, I would be excited to see it :)
Hi every one : I try to skip instruction
void func(char *str) {
char buffer[24];
int *ret;
strcpy(buffer, str);
}
int main(int argc, char **argv) {
int x;
x = 0;
func(argv[1]);
x = 1;
printf("%d\n”, x);
}
How I can use the pointer *ret defined in funct() to modify the return address for the function in such away I can skip x=1
It's a bad idea to use this in production code! (Reasons copied from dvnrrs' comment.) This is undefined behavior; it is severely abusing (assumed) knowledge about the way the stack is laid out under the hood, and the size of the compiled instructions. This is doomed to failure, especially if optimization is turned on.
Please note that modifying the memory next to local variables this way is incorrect C code, and it makes undefined behavior. I think there is no standard C solution to your problem, so if you want to do that, your best bet is architecture-specific assembly code. The following code happens to work for me in C on i386 with my GCC, but it's still undefined behavior, so it's inherently fragile and can cease to work in any changes in the compiler or in the ABI.
This prints 42 for me:
#include <stdio.h>
void func(char *str) {
(&str)[-1] += 2;
}
int main(int argc, char **argv) {
(void)argc; (void)argv;
int x;
x = 42;
func(argv[1]);
x = 137;
printf("%d\n",x);
return 0;
}
Compile and run on Linux i386:
$ gcc -m32 -W -Wall -s -O0 t.c && ./a.out
42
You can't do this in C; the closest thing would be the setjmp() and longjmp() functions but those won't work for your exact case.
As others pointed out in comments, the best thing to do might be to give your function a return value, and then check that return value in the caller to decide what code to run next. Your sample code seems like a contrived test case so I'm not sure exactly what you're trying to accomplish.
I'm experimenting with a piece of C code. Can anyone tell me why is VC 9.0 with SP1 crashing for me? Oh, and the code is meant to be an example used in a discussion why something like
void main (void)
is evil.
struct foo { int i; double d; } main (double argc, struct foo argv)
{
struct foo a;
a.d=0;
a.i=0;
return a.i;
}
If I put
return a;
compiler doesn't crash.
The code gives undefined behavior. This doesn't require the compiler to crash, it just says you've basically broken the rules, so the compiler hasn't done anything wrong, no matter what happens.
Edit: that said, as a quality of implementation issue, it's absolutely true that there's basically never an excuse for the compiler to crash -- reasonably speaking, it should always exit normally, no matter what data you feed it.
Ok you want to pose an esoteric question, then please construct a complete one.
How did you run the test?
What do you mean by crash?
What was your output?
Did you just compile, or compile and link, or compile and link and debug?
How is your compiler configured?
Where are you going with this experiment?
phrases like: "something like" "evil" are not informative enough to be useful
Follow UP:
Instinctively I'll guess that this crash is a consequence of a compiler
optimization switch with which you permit the the compiler to make
certain assumptions that you are not conforming to.
my suppositions:
1- The void main(void) (without ;) is part of a comment you are making, but not
part of the test you submitted.
2- Your program is incorrect, but this is deliberate in order to investigate
the behaviour of the compiler/linker/execution environment.
If this is indeed the case, you need to reduce the complexity of the test case.
Please simplify the test case to the bare minimum it takes to cause a crash.
I can't do it for you, I don't have the correct versions of software
installed, anyway, it's your experiment.
will this crash?
struct foo { int i; double d; };
struct foo main( void)
{
int a=0;
return a;
}
or even this most minimal example?
void * main(void)
{
return 0;
}
of is it this (I doubt it):
int main( double argc, char ** argv)
{
return 0;
}
You get the idea. reduce the crash to it's essence.
Come up with a program that is error free except for the
one thing that will make it crash.
Then report back.
put a semi colon between the end of your structure and main like so:
struct foo { int i; double d; }; main (double argc, struct foo argv)
you could also define a return type for main if your gonna return something:
struct foo { int i; double d; }; int main (double argc, struct foo argv)