{"id":43873,"date":"2014-10-10T07:00:00","date_gmt":"2014-10-10T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/10\/10\/some-parts-of-an-interface-can-change-but-others-cant\/"},"modified":"2014-10-10T07:00:00","modified_gmt":"2014-10-10T07:00:00","slug":"some-parts-of-an-interface-can-change-but-others-cant","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20141010-00\/?p=43873","title":{"rendered":"Some parts of an interface can change but others can&#039;t"},"content":{"rendered":"<p>\nWhen I wrote about\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/02\/20\/10395379.aspx\">\nasking the compiler to answer calling convention questions<\/a>,\nsome people were concerned about whether this was a reliable mechanism\nor whether it was relying on something that can change in the future.\n<\/p>\n<p>\nThis is a special case of the question,\n&#8220;What parts of an interface can change, and what can&#8217;t?&#8221;\nAnd it all boils down to compile-time versus run-time.\n<\/p>\n<p>\nAssuming you are interested in binary compatibility\n(as opposed to merely source compatibility),\nthen\na decision made at compile-time can never be changed\nbecause the decision is already hard-coded into the application.\nFor example, if you have a function that takes a parameter that is\nan enumeration, say,\n<\/p>\n<pre>\nenum FOO_OPTIONS\n{\n    FOO_HOP = 0,\n    FOO_SKIP = 1,\n    FOO_JUMP = 2,\n};\n<\/pre>\n<p>\nthen the values of\n<code>FOO_HOP<\/code>,\n<code>FOO_SKIP<\/code>,\nand\n<code>FOO_JUMP<\/code>\nare hard-coded into any program that uses them.\nThe compiler will generate code like this:\n<\/p>\n<pre>\n; foo(FOO_JUMP);\n    push 2\n    call foo\n<\/pre>\n<p>\nSuppose you later change the header file to\n<\/p>\n<pre>\nenum FOO_OPTIONS\n{\n    FOO_HOP = 2,\n    FOO_SKIP = 3,\n    FOO_JUMP = 4,\n};\n<\/pre>\n<p>\nMaking a change in the new version of a header file\nhas no effect on any existing programs which were\ncompiled with the old version of the header file.\nThere is no way for the <code>foo<\/code> function to tell\nwhether the <code>2<\/code> it received as a parameter is a\n<code>FOO_JUMP<\/code> from the old header file or\na <code>FOO_HOP<\/code> from the new one.\n<\/p>\n<p>\nTherefore, you cannot reuse values in any\nexisting enumerations\nor <code>#define<\/code>&#8216;s because the values are already compiled\ninto existing programs.\nIf you had given the value <code>2<\/code> different meanings in different\nversions of the header file,\nyou would have in principle\nno way of knowing which header file the caller used.\nOf course, you can invent external cues to let you figure it out;\nfor example, there may be a separate <code>set_foo_version<\/code>\nfunction\nthat callers use in order to specify whether they are using the\nold or new header file.\nOf course, that also means that if there are multiple components that\ndisagree on what version of <code>foo<\/code> they want,\nyou have another problem.\n<\/p>\n<p>\nNote that this is not the same as saying that the value of a symbol\ncannot change.\nWe&#8217;ve seen this happen in the past\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2009\/04\/23\/9564015.aspx\">\nwith the <code>PSH_WIZARD&shy;97<\/code> flag<\/a>,\nbut these sorts of redirections are rare in practice.\n<\/p>\n<p>\nAnother thing that is hard-coded into an application is the calling\nconvention.\nOnce code is generated by the compiler to call a function,\nthat&#8217;s that.\nYou can&#8217;t change the calling convention without breaking existing code.\nThat&#8217;s why you can ask the compiler,\n&#8220;How would you call this function?&#8221;\nand trust the answer:\nIf the compiler generates code to call the function using technique&nbsp;X\n(register set-up, what gets pushed on the stack first, <i>etc<\/i>.),\nthen\nthe function had better accept technique&nbsp;X in perpetuity.\nOf course, you need to be sure that what you observe is in fact all\nthere is.\nThere may be parts of the calling convention that are not obvious to you,\nsuch as\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/01\/02\/47184.aspx\">\nthe presence of a red zone<\/a>\nor\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/01\/14\/58579.aspx\">\nmaintaining a particular stack alignment<\/a>.\nOr it could be that the function is called only from within\nthe module, and the compiler&#8217;s whole-program optimization decided\nto use a custom nonstandard calling convention.\n<\/p>\n<p>\nOn the other hand, things determined at run-time can be changed,\nprovided they are changed in a manner consistent with their original\ndocumentation.\nFor example, the message numbers returned by\n<code>Register&shy;Window&shy;Message<\/code> can change\nbecause the documentation specifically requires you to call\n<code>Register&shy;Window&shy;Message<\/code> to obtain the\nmessage number for a particular named message.\n<\/p>\n<p>\nIf you want to know how to call a function,\nit&#8217;s perfectly valid to ask the compiler,\nbecause at the end of the day,\nthat&#8217;s how the function gets called.\nIt&#8217;s all machine code.\nWhether that machine code was generated by a compiler\nor by an assembler is irrelevant.\n<\/p>\n<p>\n<b>Caveat<\/b>: I&#8217;m ignoring whole-program optimization\nand link-time code generation,\nwhich allow the toolchain to rewrite calling conventions\nif all callers can be identified.\nWe&#8217;ll see more about this in a future article.\nThe technique described in this article works best with\nexported\/imported functions,\nbecause it is not possible to identify all callers of\nsuch functions,\nand the compiler is forced to use the official calling convention.\n(You can also use it when inspecting .COD files for\nfunctions defined in a separate translation unit,\nfor the same reason.\nThat&#8217;s the technique I used in the linked article.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I wrote about asking the compiler to answer calling convention questions, some people were concerned about whether this was a reliable mechanism or whether it was relying on something that can change in the future. This is a special case of the question, &#8220;What parts of an interface can change, and what can&#8217;t?&#8221; And [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-43873","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>When I wrote about asking the compiler to answer calling convention questions, some people were concerned about whether this was a reliable mechanism or whether it was relying on something that can change in the future. This is a special case of the question, &#8220;What parts of an interface can change, and what can&#8217;t?&#8221; And [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=43873"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43873\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=43873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=43873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=43873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}