This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How does a compiled C++ class look like?
Hi all,
bash$cat struct.c
struct test
{
int i;
float f;
};
bash$gcc -c struct.c
The object file struct.o is of elf format. I am trying to understand what does this object file contain. The source code is just a definition of a struct. There is nothing executable here so there should be nothing in text, and there is no data really either.
So where does the definition of struct go really?
I tried using;
readelf -a struct.o
objdump -s struct.o
but don't quite understand this.
Thanks,
Jagrati
So where does the definition of struct
go really?
Struct definition usually goes to /dev/null. C does not have any introspection features, so struct definition is not needed at run time. During compilation, calls to struct fields are converted to numeric offsets, eg. x->f would be compiled to equivalent of *((void*)x + sizeof(int)). That's why you need to include headers every time you use struct.
There is nothing. It does not exist. You have created nothing and used nothing.
The definition of the struct is used at compile time. That definition would normally be placed in a non-compiled header file. It is when a struct is used that some code is generated. The definition affects what the compiler produces at that point.
This, among other reasons, is why compiling against one version of a library and then using another version at runtime can crash programs.
structs are not compiled, they are declared. Functions get compiled though.
I'm not an expert and I can't actually answer the question... But I thought of this.
Memory is memory: if you use 1 byte as integer or char, it is still one byte. The results depends only on the compiler.
So, why can't be the same for structs? I mean, the compiler probably will calculate the memory to allocate (as your computer probably will allocate WORDS of memory, not bytes, if your struct is 1 byte long, probably 3 bytes will be added allowing the allocation of 4 bytes word), and then struct will just be a "reference" for you when accessing data.
I think that there is no need to actually HAVE something underneath: it's sufficient for the compiler to know that, in compile time, if you refer to field "name" of your struct, it shall treat is as an array of chars of length X.
As I said, I'm not expert in such internals, but as I see it, there is no need for a struct to be converted in "real code"... It's just an annotation for the compiler, which can be destroyed after the compilation is done.
Related
I'm developing on a custom embedded platform with a custom version of gcc, which is based on gcc-2.8.0 (egcs-2.91.02). Yes, it's old. It's for a CoolRISC C816 core.
I face a strange error sometimes, when during the link of my embedded C project gcc gives me this error :
undefined reference to _spill
Indeed, when looking into the temporary *.s file generated by gcc when compiling the source files in those specific cases, I see this kind of instruction :
MOVE __spill+4,%a
I'm surprised because this _spill error only happens once in a while, on multiple big projects (20k+ LOC) there's no sign of this error, and not any reference to _spill in the *.s files.
I already have a fix consisting of allocating _spill in my startup assembly file, but I'd like to know more about this.
What is '_spill' and why do I need it ? Also, if I have to statically allocate it, how to know which size I should give it ?
Edit: As advised in the comments, I looked at the corresponding C code and the line that seems the source of the pack of instructions containing '_spill' is this one :
pStruct->psConst->puRegister[CONST_VALUE] = 0x00;
Where pStruct is a pointer on a typedef struct (call it Foo) locally declared like this : Foo *pStruct = &MyStruct, with MyStruct an extern variable of type Foo that is in another file.
psConst is a const pointer on another typedef struct (call it Bar).
puRegister is a member of Bar declared of type volatile uint8_t *
And finally, CONST_VALUE is a constant value from an enumerate.
This might therefore be an issue that happens only when there's a lot of dereference in a row, or something related.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm interested in creating my own implementation of a doubly-linked list in C. The goal is to make it as flexible and "user" friendly as possible. This means it can't be restricted to one type of data. I'd also like to minimize memory management outside of the list code. That is, I want the list code to handle allocating and freeing any necessary memory. (But, of course, the list could be used to store pointers to dynamically-allocated data.)
I'm using two structs. The "node" struct holds pointers to the node immediately before it and the node immediately following it, a void* pointer to the data it contains, and the size of the data. However, because this is C, it can't hold the type of data. The "list" struct keeps track of the beginning and end of the list, the number of elements in the list, and so on. I've already implemented the functions for initializing the list and appending data to the list. The memory allocation and deallocation and linking seem to be working fine, and the lists appear to link to one another properly. The problem is how to actually import the data when creating a list node. Here are the approaches I've considered:
Passing a pointer to the data through a void* and the size as another argument. This could be made more user-friendly by adding a macro to take the address and size of a variable and pass those to the function. The problem? Not everything I might want to add to the list can have its address taken. For example, consider list_append(list, 17). This should add a new node with an integer payload of value 17 to the end of the list, but it would not work because the integer literal 17 can't have its address taken.
Passing the size of the data as one argument and the data itself on the call stack as an extra argument. C supports arguments of unknown number, type, and size though the .../stdarg.h method. I figured I could use a macro to take the sizeof() the item being appended and pass this along with the item itself to the appending function. The problem here is that the varargs macros want me to specify a type (not just the size of the type). So, I did some digging and found that GCC apparently uses the __builtin_next_arg macro to implement variable arguments in stdarg.h. Obviously, this would make my code dependent on GCC (or, at least, on this particular macro), but it might work at least with this particular compiler. The __builtin_next_arg macro allegedly gives the address of the argument following the last named one on the argument list as a void*. When I tried this approach on Windows (using MinGW 32-bit), it worked as intended. A simple memcpy() from the value given by __builtin_next_arg to the newly allocated buffer copied the data. However, when I used GCC 64-bit on Ubuntu, all hell broke loose. __builtin_next_arg was giving me addresses very far from where I'd expect the argument to be. The compiler also started occasionally complaining about the second argument to va_start wasn't the last argument in the list, despite the fact that I don't even use va_start in my code at all. Also, no matter what I did, the values I seemed to be getting were zeros (NULL, 0).
Is there a way I could fix this? What I basically want is a version of va_arg that gives the address of the argument on the stack. Other approaches are also acceptable.
In C++, I would be able to use templates to avoid this problem entirely, but I want to use C.
I would recommend you either not use __builtin_* functions at all or thoroughly study their implementations by reading the docs/gcc sources/asm compiler output of simple functions you code just to see how it works.
First, the behavior of specifically __builtin_next_arg could be completely different between mingw and linux environment because of different ABI in use.
Next, the __builtin_* function(s) may be superseded by another one(s) in a different gcc version. For example, in gcc-4.8.3 (linux build, to be precise) va_* macroses are implemented using
__builtin_va_start(), __builtin_va_end() and __builtin_va_arg() functions and there is no occurrences of __builtin_next_arg in the gcc internal header files.
No, you cannot use the __builtin_next_arg here. The reason is that even with __builtin_next_arg and such, your called function must know the type of data.
And no, function arguments are not stored on stack in say Linux x86-64 ABI; the first 6 arguments are provided in registers. And the registers depend on their types, so float and int are in different register, even though both are of size 4. Sorry, you just cannot do it like this, even in a particular GCC version on this ABI.
However if you're using C11, you can use a macro, that uses static_assert to assert the sizeof object passed in; then you can use some _Generic tricks to store different types into a struct that contains char contents[sizeof val];, something like:
#include <assert.h>
#include <string.h>
#define VALUE_SIZE (sizeof(int))
struct list;
struct value_type {
char contents[VALUE_SIZE];
};
int _list_append(struct list *l, struct value_type v);
struct value_type coerce_float(float arg) {
struct value_type rv;
memcpy(&arg, rv.contents, sizeof arg);
return rv;
}
struct value_type coerce_int(int arg) {
struct value_type rv;
memcpy(&arg, rv.contents, sizeof arg);
return rv;
}
static_assert(sizeof(float) == VALUE_SIZE,
"code relies on float and int being of the same size");
#define coerce_arg(X) (_Generic((X), \
float: coerce_float, \
int: coerce_int, \
void*: coerce_int \
)((int)X))
#define list_append(L, X) _list_append(L, coerce_arg(X))
list_append(l, 4);
list_append(l, 4.0f);
list_append(l, (void*)0); // will throw an error since it is not supported
This is quite portable, but note that for example MSVC compiler does not even support C99. GCC and LLVM shouldn't have problems. However on the con side, you must add each supported compatible type by hand. Including each pointer type, or cast your pointers to say (void*).
If you're ok with using only GCC I believe you can write a macro that uses typeof to make a variable of the exact argument type, then memcpy its contents directly into this struct.
I'm pretty new to c programming and I have this following program to degub. Problem is, I have no idea what these lines of code even mean. Could anyone point me in the direction of what they mean as far as from a syntax point of view/functionality? What does the code do? The code is compiled with MPLab C30 v3.23 or higher.
fractional abcCoefficient[3] __attribute__ ((space(xmemory))); /*ABC Coefficients loaded from X memory*/
fractional controlHistory[3] __attribute__ ((space(ymemory))); /*Control History loaded from Y memory*/
fractional kCoeffs[] = {0,0,0}; /*Kp,Ki,and Kd gains array initialized to zero*/
These lines declare variables; there's no execution code associated with what you've pasted.
The environment this code is intended for understands that fractional is a type; either in the same file or in a header this file includes (directly or indirectly), fractional will be defined with a typedef statement. In your examples, each of the variables are arrays of three fractional types.
The __attribute__ ((space(?memory))) entries are attributes the compiler intended to build this understands and affect something regarding how the variables are managed. You'll want to consult the compiler documentation for the platform you're using.
See this page to learn about __attribute__ in gcc (however, I don't see a space(xmemory) option in there, consult your compiler's documentation if it's not gcc. If it is, then space() can be a macro).
fractional is also a custom type, search for typedef definitions for fractional.
Basically, the code is creating a bunch of arrays of type fractional. The first two make use of gcc's attribute extension (or whatever compiler you are using), and the last one is initialized to 0 on every position.
The first two lines declare arrays with three elements each. The type is fractional, which is probably a typedef (to a struct with numerator and denominator?).
The comments suggest that the data is stored in another memory space, perhaps some sort of Flash.
So the program seems to be for an embedded system.
It looks like "fractional" is a custom type, look for its typedef somewhere and it should get you started on what you're looking at. I expect these are variable declarations.
Macros are established using the "#define" preprocessor directive, so you can look for "#define space(x) code" somewhere to tell you what it does. Good luck.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to LD_PRELOAD a function with different parameters?
I have a structure, lets call it my_struct, which is declared as follows.
struct my_struct
{
int a;
int b;
}
For some reason I want to add a new field to it, so I want to change it as follows.
struct my_struct
{
int a;
int b;
int c;
}
Say I do this in my shared object library which I then LD_PRELOAD to run the program. Will my program use the second definition or the original one.
No, the original code will not use the new definition. Imagine the case if it did and what would have to change. Firstly, each my_struct on the heap would have to be expanded to include the new field. This would likely mean that data sections have to be resized and all data that is shifted forward would need its references relocated. sizeof struct my_struct, which is evaluated at compile-time would then be inconsistent with the new definition. These are just a few of the reasons which make what you are trying to do impossible (at least in the way you're attempting).
The original code that was compiled and linked against the old definition will continue to use the old my_struct. Any new code in your shared object will be compiled against and use the new definition and hence will have a c field.
Once the original program has been compiled, it does not know anything about my_struct. That information is just used by the compiler to generate offsets to access structure members and allows it to know how to lay it out in memory. It is possible that information is still available in the form of symbols but this would not effect how the definition is picked up. Unlike function resolution, the code/data generation and resolution of a structure is strictly a compile-time operation.
I'm trying to connect to mysql from rust code. I've tried these steps.
1. I wrote c code using mysql.h, and command below.
$ gcc -shared mysqlrust.c -o libmysqlrust.so $(mysql_config --cflags) $(mysql_config --libs) $(mysql_config --cflags)
$ cp libmysqlrust.so /usr/local/lib/rustc/i686-unknown-linux-gnu/lib/
2. I wrote Rust code, that calls libmysqlrust.so.
But I couldn't figure out way to use C type structure "MYSQL", "MYSQL_RES", "MYSQL_ROW".
Please show me how to use c type structure from rust code.
There is not yet any way to automatically create Rust type definitions from C structs. In these situations there are a few ways to proceed. Not knowing the MySQL API, I can't say exactly what you should do, but here are some options.
1) Treat them entirely as opaque pointers.
This is the best situation to be in, and depends on the C API always taking the struct as a pointer, having its own constructor and destructor functions, and providing accessor functions for whatever you need to access inside the struct. In these cases you just define type MYSQL = ctypes::void and only ever use it as an unsafe pointer *MYSQL. Sometimes the easiest path is to write your own C wrappers to fill in the gaps and make this scenario possible.
The remaining scenarios all involve redefining a Rust data structure with the same structure as the C struct. Rust tries to lay out its data structures in a way that is compatible with C (though doesn't always succeed yet), so it is often possible to create a Rust record or enum with the size, alignment and layout of the C struct you care about. You will want to make sure you use the types in core::ctypes, as they are defined to match various common C types.
Note that the ctypes module will be going away soon in favor of a more comprehensive libc compatibility module.
2) Define a Rust record that is partially correct.
If the API provides constructors and destructors, but you still need access to some fields of the struct, then you can define just enough of the struct to get at the fields you care about, disregarding things like the correct size and alignment. e.g. type MSQL = { filler1: ctypes::int, ..., connector_fd: *ctypes::char }. You can stop defining the struct at the last field you care about since you have a C function to allocate it on the heap with the correct size and alignment. In Rust code you always refer to it with an unsafe pointer: let mysql: *MYSQL = mysqlrust::create_mysql();
3) Define a Rust record that is the correct size and alignment, without caring about the contents.
If you don't have constructor/destructor functions, or need to store the struct on the stack, but you otherwise have accessor functions to manipulate the contents of the struct, then you need to define a Rust record with the correct size and alignment. To do this, just add fields of type uint (which is always pointer-sized) or tuples of uint, until both C's sizeof and core::sys::size_of agree on the size. Pad with u8s if the size isn't a multiple of the pointer size. Getting the alignment right is a more mystical process, but by using uint fields you will generally end up with a usable alignment (maybe - I really have no idea how accurate that statement is).
I would recommend adding tests to sanity check that Rust and C agree on the size in order to guard against future breakage.
3) Actually redefine the entire C struct.
This is a pretty dire situation for large structs, and it is possible in theory, but I don't think anybody has done it for a struct as big as MYSQL. I would avoid it if you can. Eventually there will be a clang-based tool to do this automatically.
Here are some examples of interop with C structs:
https://github.com/jdm/rust-socket/blob/master/socket.rs - This redefines various socket structs, adding placeholders for fields it doesn't care about. Note that it uses u8 for padding, but I think uint is more likely to produce correct alignment.
https://github.com/erickt/rust-zmq/blob/master/zmq.rs
https://github.com/pcwalton/rust-spidermonkey - This one demonstrates interop with a somewhat complex API.