Is the packing alignment of __nogc classes stored as part of the assembly ? I think it must as the compiler, when referencing the assembly, could not know how the original data is packed otherwise. Yet, in my understanding, attributes are only __gc and __value class specific and do not apply to __nogc classes. Is this correct ? If so, how is the packing alignment of __nogc classes stored ?
[quoted text, click to view] .. wrote: > Its stored in a jam jar in the cupboard. >
Along with the Java coffee no doubt. [quoted text, click to view] > > "Edward Diener" <eddielee@tropicsoft.com> wrote in message > news:OPK5sM39DHA.1472@TK2MSFTNGP11.phx.gbl... >> Is the packing alignment of __nogc classes stored as part of the >> assembly ? I think it must as the compiler, when referencing the >> assembly, could not know how the original data is packed otherwise. >> Yet, in my understanding, attributes are only __gc and __value class >> specific and do not apply to __nogc classes. Is this correct ? If >> so, how is the packing alignment of __nogc classes stored ?
Its stored in a jam jar in the cupboard. [quoted text, click to view] "Edward Diener" <eddielee@tropicsoft.com> wrote in message news:OPK5sM39DHA.1472@TK2MSFTNGP11.phx.gbl... > Is the packing alignment of __nogc classes stored as part of the assembly ? > I think it must as the compiler, when referencing the assembly, could not > know how the original data is packed otherwise. Yet, in my understanding, > attributes are only __gc and __value class specific and do not apply to > __nogc classes. Is this correct ? If so, how is the packing alignment of > __nogc classes stored ? > >
Hi Edward, [quoted text, click to view] > Is the packing alignment of __nogc classes stored as part of the assembly ? > I think it must as the compiler, when referencing the assembly, could not > know how the original data is packed otherwise. Yet, in my understanding, > attributes are only __gc and __value class specific and do not apply to > __nogc classes. Is this correct ? If so, how is the packing alignment of > __nogc classes stored ?
Well, I don't think the packing is actually stored. When the compiler creates metadata (very basic metadata indeed) for __nogc classes, it does so by creating them as opaque value types, which means basically it creates them as value types containing no members, and only basic information on layout and size. Here's an example of one such __nogc class represented: ..class private sequential ansi sealed A extends [mscorlib]System.ValueType { .pack 1 .size 12 } // end of class A Notice the .pack and .size directives, which tell the runtime how to pack the type and size of the type. AFAIK, the compiler will *always* mark __nogc types with .pack 1, even if actual packing is different. However, the compiler *will* adjust the .size directive so that it reflects the real size of the object in memory according to it's packing. In this case, I was trying with a class contaning an int, a char and another int, with packing set to 4. If I set it to 1, then the code would've said ".size 9", and so on. -- Tomas Restrepo tomasr@mvps.org
[quoted text, click to view] Tomas Restrepo (MVP) wrote: > Hi Edward, > >> Is the packing alignment of __nogc classes stored as part of the >> assembly ? I think it must as the compiler, when referencing the >> assembly, could not know how the original data is packed otherwise. >> Yet, in my understanding, attributes are only __gc and __value class >> specific and do not apply to __nogc classes. Is this correct ? If >> so, how is the packing alignment of __nogc classes stored ? > > Well, I don't think the packing is actually stored. When the compiler > creates metadata (very basic metadata indeed) for __nogc classes, it > does so by creating them as opaque value types, which means basically > it creates them as value types containing no members, and only basic > information on layout and size. > > Here's an example of one such __nogc class represented: > > .class private sequential ansi sealed A > extends [mscorlib]System.ValueType > { > .pack 1 > .size 12 > } // end of class A > > Notice the .pack and .size directives, which tell the runtime how to > pack the type and size of the type.
Is this from the assembly itself ? If so, it looks like the assembly is storing a .pack directive. [quoted text, click to view] > > AFAIK, the compiler will *always* mark __nogc types with .pack 1, > even if actual packing is different.
This is strange. Suppose I need a different packing for __nogc classes to correspond to some already created data structure. How do I tell the compiler to change the packing. In non-CLR code I would use "#pragma pack". Is this still accepted in __nogc classes in a CLR assembly ? If it is, why does the compiler ignore it and always insert a .pack 1 directive ? [quoted text, click to view] > However, the compiler *will* > adjust the .size directive so that it reflects the real size of the > object in memory according to it's packing. In this case, I was > trying with a class contaning an int, a char and another int, with > packing set to 4. If I set it to 1, then the code would've said > ".size 9", and so on.
Your explanation has confused me. Could you please be clearer as to: 1) whether there is a way to set the packing size for __nogc classes. 2) what that way is. 3) whether or not the end-user changing the packing from the IDE affects the packing for __nogc classes if no specific packing has been set via 1) or 2). The reason for this post has to do with a potential common problem pre-.NET having to do with packing of classes/structures. If the programmer/creator of a struct/class does not specifically set a packing size, via the #pragma pack directive, when the compiler saw the header file it would apply whatever the packing was in the IDE ( or command-line ). This could lead to ABI problems if a library was built with a particular packing for a class/structure and the end-user of that library decided to change the global packing in the IDE ( or command-line ) to some other value. The solution to this problem was for the programmer/creator to set the packing for the class.structure in the header file for the class/structure via "#pragma pack". Then the compiler would honor this directive by overriding the end-user's global packing for that particular class/struct and all would be well with no ABI problem occurring. Every 3rd party implementation which distributed C++ header files/library would of course use the "#pragma pack" method to assure that no ABI problem would occur. I wanted to make sure that this would work properly with .NET C++ components with __nogc classes. I am, of course, assuming that __gc and __value classes store their packing as part of the metadata. My problem is that I want to be assured that for __nogc classes that the end-user changing the global packing will not affect the way the compiler/linker access data and alignment in __nogc classes. Since __nogc ( and __gc and __value ) classes in assemblies have no header file, I can only think that the packing used when the assembly is built is somehow picked up and correctly used no matter what the global packing in the IDE ( or command-line ) happens to be. If this is the case, I will not worry about putting "#pragma pack" around my __nogc classes since I don't need to change the default packing for __nogc classes.
[quoted text, click to view] Edward Diener wrote: >The reason for this post has to do with a potential common problem pre-.NET >having to do with packing of classes/structures. If the programmer/creator >of a struct/class does not specifically set a packing size, via the #pragma >pack directive, when the compiler saw the header file it would apply >whatever the packing was in the IDE ( or command-line ). This could lead to >ABI problems if a library was built with a particular packing for a >class/structure and the end-user of that library decided to change the >global packing in the IDE ( or command-line ) to some other value. The >solution to this problem was for the programmer/creator to set the packing >for the class.structure in the header file for the class/structure via >"#pragma pack". Then the compiler would honor this directive by overriding >the end-user's global packing for that particular class/struct and all would >be well with no ABI problem occurring. Every 3rd party implementation which >distributed C++ header files/library would of course use the "#pragma pack" >method to assure that no ABI problem would occur.
I think that's backwards. The real solution is to never use /Zp but instead use #pragma pack on structs only as necessary. If you expect everybody to use #pragma pack in order to write /Zp-neutral headers, you've effectively made #pragma pack part of the language, which is, to put it mildly, not a good thing. I'd personally like to see /Zp abolished, and I'd like #pragma pack to generate warnings when its effects penetrate #includes, both coming or going. An exception to this latter rule could be made for the <pshpackN.h> and <poppack.h> Windows headers. BTW, the Windows headers are not all /Zp-neutral. -- Doug Harrison
Is there good resources on runtime design, Im aware of compiler design but not about managed runtime design. [quoted text, click to view] "Tomas Restrepo (MVP)" <tomasr@mvps.org> wrote in message news:Oa5Y4lU#DHA.3436@tk2msftngp13.phx.gbl... > Hi Edward, > > > Is the packing alignment of __nogc classes stored as part of the assembly > ? > > I think it must as the compiler, when referencing the assembly, could not > > know how the original data is packed otherwise. Yet, in my understanding, > > attributes are only __gc and __value class specific and do not apply to > > __nogc classes. Is this correct ? If so, how is the packing alignment of > > __nogc classes stored ? > > Well, I don't think the packing is actually stored. When the compiler > creates metadata (very basic metadata indeed) for __nogc classes, it does so > by creating them as opaque value types, which means basically it creates > them as value types containing no members, and only basic information on > layout and size. > > Here's an example of one such __nogc class represented: > > .class private sequential ansi sealed A > extends [mscorlib]System.ValueType > { > .pack 1 > .size 12 > } // end of class A > > Notice the .pack and .size directives, which tell the runtime how to pack > the type and size of the type. > > AFAIK, the compiler will *always* mark __nogc types with .pack 1, even if > actual packing is different. However, the compiler *will* adjust the .size > directive so that it reflects the real size of the object in memory > according to it's packing. In this case, I was trying with a class contaning > an int, a char and another int, with packing set to 4. If I set it to 1, > then the code would've said ".size 9", and so on. > > -- > Tomas Restrepo > tomasr@mvps.org > >
Hi Edward, [quoted text, click to view] > Is this from the assembly itself ? If so, it looks like the assembly is > storing a .pack directive.
Yes, it's part of the actual managed metadata in the assembly. [quoted text, click to view] > > AFAIK, the compiler will *always* mark __nogc types with .pack 1, > > even if actual packing is different. > > This is strange. Suppose I need a different packing for __nogc classes to > correspond to some already created data structure.
Wouldn't be a problem. I already explained how the compiler deals with it: by telling the runtime the actual size of objects of that type, which already takes into account packing. See, the .pack directive in managed metadata serves to tell the runtime when laying out a type how to organize members. Since __nogc classes are opaque to the runtime, really, there are no members the runtime can lay out, so the compíler "fools" it by telling it the actual size of the resulting object so that the runtime can reserve the memory correctly on the stack or as part as a __gc type. [quoted text, click to view] > How do I tell the > compiler to change the packing.
For __nogc type, same way you always have (#pragma pack). [quoted text, click to view] > Your explanation has confused me. Could you please be clearer as to: > > 1) whether there is a way to set the packing size for __nogc classes.
Yes, see above. [quoted text, click to view] > 2) what that way is.
Again, see above. [quoted text, click to view] > 3) whether or not the end-user changing the packing from the IDE affects the > packing for __nogc classes if no specific packing has been set via 1) or
2). See above, Keep in mind, though, that AFAICS, managed metadata is probably NOT enough for the compiler to "guess" what the original packing of the __nogc type is, which is where having the original header file defining it helps :) -- Tomas Restrepo tomasr@mvps.org
[quoted text, click to view] Doug Harrison [MVP] wrote: > Edward Diener wrote: > >> The reason for this post has to do with a potential common problem >> pre-.NET having to do with packing of classes/structures. If the >> programmer/creator of a struct/class does not specifically set a >> packing size, via the #pragma pack directive, when the compiler saw >> the header file it would apply whatever the packing was in the IDE ( >> or command-line ). This could lead to ABI problems if a library was >> built with a particular packing for a class/structure and the >> end-user of that library decided to change the global packing in the >> IDE ( or command-line ) to some other value. The solution to this >> problem was for the programmer/creator to set the packing for the >> class.structure in the header file for the class/structure via >> "#pragma pack". Then the compiler would honor this directive by >> overriding the end-user's global packing for that particular >> class/struct and all would be well with no ABI problem occurring. >> Every 3rd party implementation which distributed C++ header >> files/library would of course use the "#pragma pack" method to >> assure that no ABI problem would occur. > > I think that's backwards. The real solution is to never use /Zp but > instead use #pragma pack on structs only as necessary. If you expect > everybody to use #pragma pack in order to write /Zp-neutral headers, > you've effectively made #pragma pack part of the language, which is, > to put it mildly, not a good thing. I'd personally like to see /Zp > abolished, and I'd like #pragma pack to generate warnings when its > effects penetrate #includes, both coming or going. An exception to > this latter rule could be made for the <pshpackN.h> and <poppack.h> > Windows headers. BTW, the Windows headers are not all /Zp-neutral.
I create a 3rd party header and library. I build it with packing set to 8 which is the default. I don't use #pragma pack around my classes as you suggest. I distribute it ands the end-user sets his /Zp to 4 when including my header file. Guess what ? My library is broken. However, if I had used #pragma pack(push,8) prior to my class definition in the header file and #pragma pack(pop) after my class definition in the header file, everything works fine no matter what the end-user does. And you are telling me that you think that is backward ? As far as abolishing /Zp, how in the world do you expect programmers to set packing, or perhaps you don't. If they have a data structure which requires packing of 1, but they must use the deafult packing of 8, I guess they are just out of luck, huh ? You are way off base, sir, and have chosen to make a silly comment for some reason I can't even begin to guess.
[quoted text, click to view] Edward Diener wrote: >Doug Harrison [MVP] wrote: >> Edward Diener wrote: >> >>> The reason for this post has to do with a potential common problem >>> pre-.NET having to do with packing of classes/structures. If the >>> programmer/creator of a struct/class does not specifically set a >>> packing size, via the #pragma pack directive, when the compiler saw >>> the header file it would apply whatever the packing was in the IDE ( >>> or command-line ). This could lead to ABI problems if a library was >>> built with a particular packing for a class/structure and the >>> end-user of that library decided to change the global packing in the >>> IDE ( or command-line ) to some other value. The solution to this >>> problem was for the programmer/creator to set the packing for the >>> class.structure in the header file for the class/structure via >>> "#pragma pack". Then the compiler would honor this directive by >>> overriding the end-user's global packing for that particular >>> class/struct and all would be well with no ABI problem occurring. >>> Every 3rd party implementation which distributed C++ header >>> files/library would of course use the "#pragma pack" method to >>> assure that no ABI problem would occur. >> >> I think that's backwards. The real solution is to never use /Zp but >> instead use #pragma pack on structs only as necessary. If you expect >> everybody to use #pragma pack in order to write /Zp-neutral headers, >> you've effectively made #pragma pack part of the language, which is, >> to put it mildly, not a good thing. I'd personally like to see /Zp >> abolished, and I'd like #pragma pack to generate warnings when its >> effects penetrate #includes, both coming or going. An exception to >> this latter rule could be made for the <pshpackN.h> and <poppack.h> >> Windows headers. BTW, the Windows headers are not all /Zp-neutral. > >I create a 3rd party header and library. I build it with packing set to 8 >which is the default. I don't use #pragma pack around my classes as you >suggest. I distribute it ands the end-user sets his /Zp to 4 when including >my header file. Guess what ? My library is broken.
So is <windows.h>. So are any number of other headers which don't use #pragma pack. The mistake is the user's for changing the default packing, not the library author's for failing to use a #pragma (non-standard by definition) to control something outside the language definition. [quoted text, click to view] >However, if I had used #pragma pack(push,8) prior to my class definition in >the header file and #pragma pack(pop) after my class definition in the >header file, everything works fine no matter what the end-user does. And you >are telling me that you think that is backward ?
Completely backwards. I explained why in my last message, which is quoted in full above. [quoted text, click to view] >As far as abolishing /Zp, how in the world do you expect programmers to set >packing, or perhaps you don't. If they have a data structure which requires >packing of 1, but they must use the deafult packing of 8, I guess they are >just out of luck, huh ?
Like I said in my last message, they should use #pragma pack to establish non-default packing on the structs that require it. [quoted text, click to view] >You are way off base, sir, and have chosen to make a silly comment for some >reason I can't even begin to guess.
You might want to consider dialing the rudeness back a few notches and thinking about things a bit more carefully before replying. -- Doug Harrison
[quoted text, click to view] Doug Harrison [MVP] wrote: > Edward Diener wrote: > >> Doug Harrison [MVP] wrote: >>> Edward Diener wrote: >>> >>>> The reason for this post has to do with a potential common problem >>>> pre-.NET having to do with packing of classes/structures. If the >>>> programmer/creator of a struct/class does not specifically set a >>>> packing size, via the #pragma pack directive, when the compiler saw >>>> the header file it would apply whatever the packing was in the IDE >>>> ( or command-line ). This could lead to ABI problems if a library >>>> was built with a particular packing for a class/structure and the >>>> end-user of that library decided to change the global packing in >>>> the IDE ( or command-line ) to some other value. The solution to >>>> this problem was for the programmer/creator to set the packing for >>>> the class.structure in the header file for the class/structure via >>>> "#pragma pack". Then the compiler would honor this directive by >>>> overriding the end-user's global packing for that particular >>>> class/struct and all would be well with no ABI problem occurring. >>>> Every 3rd party implementation which distributed C++ header >>>> files/library would of course use the "#pragma pack" method to >>>> assure that no ABI problem would occur. >>> >>> I think that's backwards. The real solution is to never use /Zp but >>> instead use #pragma pack on structs only as necessary. If you expect >>> everybody to use #pragma pack in order to write /Zp-neutral headers, >>> you've effectively made #pragma pack part of the language, which is, >>> to put it mildly, not a good thing. I'd personally like to see /Zp >>> abolished, and I'd like #pragma pack to generate warnings when its >>> effects penetrate #includes, both coming or going. An exception to >>> this latter rule could be made for the <pshpackN.h> and <poppack.h> >>> Windows headers. BTW, the Windows headers are not all /Zp-neutral. >> >> I create a 3rd party header and library. I build it with packing set >> to 8 which is the default. I don't use #pragma pack around my >> classes as you suggest. I distribute it ands the end-user sets his >> /Zp to 4 when including my header file. Guess what ? My library is >> broken. > > So is <windows.h>. So are any number of other headers which don't use > #pragma pack. The mistake is the user's for changing the default > packing, not the library author's for failing to use a #pragma > (non-standard by definition) to control something outside the > language definition.
This is incorrect. Windows.h, and all windows related header files, as well as all MS RTL header files, guard against the user changing the default packing through /Zp. They use pushpackn.h and poppack.h header files in order to do this. These header files use the same #pragma pack(n) and #pragma pop I was discussing when VC++ is involved. Borland also does the same for their header files. Essentially MS and Borland do just what I do, which you are claiming is backward. Fine, believe what you will. I am not going to comment further. Do things your own way and I will do them in my own way.
[quoted text, click to view] Tomas Restrepo (MVP) wrote: > Hi Edward, > >> Is this from the assembly itself ? If so, it looks like the assembly >> is storing a .pack directive. > > Yes, it's part of the actual managed metadata in the assembly. > >>> AFAIK, the compiler will *always* mark __nogc types with .pack 1, >>> even if actual packing is different. >> >> This is strange. Suppose I need a different packing for __nogc >> classes to correspond to some already created data structure. > > Wouldn't be a problem. I already explained how the compiler deals > with it: by telling the runtime the actual size of objects of that > type, which already takes into account packing. See, the .pack > directive in managed metadata serves to tell the runtime when laying > out a type how to organize members. Since __nogc classes are opaque > to the runtime, really, there are no members the runtime can lay out, > so the compíler "fools" it by telling it the actual size of the > resulting object so that the runtime can reserve the memory correctly > on the stack or as part as a __gc type. > >> How do I tell the >> compiler to change the packing. > > For __nogc type, same way you always have (#pragma pack). > >> Your explanation has confused me. Could you please be clearer as to: >> >> 1) whether there is a way to set the packing size for __nogc classes. > > Yes, see above. > >> 2) what that way is. > Again, see above. > >> 3) whether or not the end-user changing the packing from the IDE >> affects the packing for __nogc classes if no specific packing has >> been set via 1) or 2). > > See above, Keep in mind, though, that AFAICS, managed metadata is > probably NOT enough for the compiler to "guess" what the original > packing of the __nogc type is, which is where having the original > header file defining it helps :)
Thanks for all the info.
[quoted text, click to view] Edward Diener wrote: >Doug Harrison [MVP] wrote: >> Edward Diener wrote: >> >>> Doug Harrison [MVP] wrote: >>>> Edward Diener wrote: >>>> >>>>> The reason for this post has to do with a potential common problem >>>>> pre-.NET having to do with packing of classes/structures. If the >>>>> programmer/creator of a struct/class does not specifically set a >>>>> packing size, via the #pragma pack directive, when the compiler saw >>>>> the header file it would apply whatever the packing was in the IDE >>>>> ( or command-line ). This could lead to ABI problems if a library >>>>> was built with a particular packing for a class/structure and the >>>>> end-user of that library decided to change the global packing in >>>>> the IDE ( or command-line ) to some other value. The solution to >>>>> this problem was for the programmer/creator to set the packing for >>>>> the class.structure in the header file for the class/structure via >>>>> "#pragma pack". Then the compiler would honor this directive by >>>>> overriding the end-user's global packing for that particular >>>>> class/struct and all would be well with no ABI problem occurring. >>>>> Every 3rd party implementation which distributed C++ header >>>>> files/library would of course use the "#pragma pack" method to >>>>> assure that no ABI problem would occur. >>>> >>>> I think that's backwards. The real solution is to never use /Zp but >>>> instead use #pragma pack on structs only as necessary. If you expect >>>> everybody to use #pragma pack in order to write /Zp-neutral headers, >>>> you've effectively made #pragma pack part of the language, which is, >>>> to put it mildly, not a good thing. I'd personally like to see /Zp >>>> abolished, and I'd like #pragma pack to generate warnings when its >>>> effects penetrate #includes, both coming or going. An exception to >>>> this latter rule could be made for the <pshpackN.h> and <poppack.h> >>>> Windows headers. BTW, the Windows headers are not all /Zp-neutral. >>> >>> I create a 3rd party header and library. I build it with packing set >>> to 8 which is the default. I don't use #pragma pack around my >>> classes as you suggest. I distribute it ands the end-user sets his >>> /Zp to 4 when including my header file. Guess what ? My library is >>> broken. >> >> So is <windows.h>. So are any number of other headers which don't use >> #pragma pack. The mistake is the user's for changing the default >> packing, not the library author's for failing to use a #pragma >> (non-standard by definition) to control something outside the >> language definition. > >This is incorrect. Windows.h, and all windows related header files, as well >as all MS RTL header files, guard against the user changing the default >packing through /Zp.
Sigh. For years, I've been advising people to stay away from /Zp. Read this recent thread to understand why: http://groups.google.com/groups?threadm=5A999D28-D21C-42A1-89FA-AA3CBAD52263%40microsoft.com In that thread, it was determined that <wincon.h> is not /Zp-immune, which is why I said in my first message to you, "the Windows headers are not all /Zp-neutral," and as it's #included by <windows.h>, why I said in my second message to you, "So is <windows.h>," in reference to /Zp breaking your library. [quoted text, click to view] >They use pushpackn.h and poppack.h header files in >order to do this.
Which is why I mentioned them in my first message to you. I'm not suggesting wrecking their functionality. [quoted text, click to view] >These header files use the same #pragma pack(n) and >#pragma pop I was discussing when VC++ is involved. Borland also does the >same for their header files. Essentially MS and Borland do just what I do, >which you are claiming is backward.
They _try_ to do that in order to accommodate the misguided /Zp compiler option, but inevitably, headers are missed. Then there's all the third party code out there which doesn't even try to do it. [quoted text, click to view] >Fine, believe what you will. > >I am not going to comment further. Do things your own way and I will do them >in my own way.
Too bad. I would have liked to have learned if you have a compelling reason to want to facilitate and thus perpetuate the use of /Zp. It typically just doesn't work right, because the necessary #pragmas aren't practiced universally, not by a long shot, and even when they are intended to be used, people tend to slip up and miss some, as with <wincon.h>. With that in mind, I'll continue to point out that /Zp is best avoided by people who don't enjoy chasing obscure bugs and by library authors who don't want to aggravate their customers. Several years ago, I used a library that actually used /Zp1 in its makefile. I had to go through and add the #pragmas to its header files, because changing the default packing in my program was not an option. It's not an option for anybody, really. But as you said, "Fine, believe what you will." Myself, I'll continue to believe what my experience has taught me over the years. :) -- Doug Harrison
Don't see what you're looking for? Try a search.
|