title: Why does setjmp() take 2 args on windows but only 1 arg on linux?
body: <p>This <strong>setjmp.c</strong> builds in windows under Microsoft Visual Studio Professional 2019 (Version 16.10.1)</p>
  <pre><code>Rebuild started...
  1&gt;------ Rebuild All started: Project: setjmp, Configuration: Release x64 ------
  1&gt;setjmp.c
  1&gt;C:\Users\john\source\repos\setjmp\setjmp.c(48,10): warning C4013: 'setjmp' undefined; assuming extern returning int
  1&gt;Generating code
  1&gt;Previous IPDB not found, fall back to full compilation.
  1&gt;All 1 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
  1&gt;Finished generating code
  1&gt;setjmp.vcxproj -&gt; C:\Users\john\source\repos\setjmp\x64\Release\setjmp.exe
  1&gt;Done building project &quot;setjmp.vcxproj&quot;.
  ========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
  </code></pre>
  <p>The actual cl.exe C compiler command is</p>
  <pre><code>1&gt;    C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30037\bin\HostX86\x64\CL.exe /c /Zi /nologo /W3 /WX- /diagnostics:column /sdl /O2 /Oi /GL /D NDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /fp:precise /permissive- /Zc:wchar_t /Zc:forScope /Zc:inline /Fo&quot;x64\Release\\&quot; /Fd&quot;x64\Release\vc142.pdb&quot; /external:env:EXTERNAL_INCLUDE /external:W3 /Gd /TC /FC /errorReport:prompt setjmp.c
  </code></pre>
  <p>The source code is</p>
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stddef.h&gt;
  #include &lt;stdint.h&gt;
  
  typedef         uint64_t QWORD;
  typedef         uint32_t DWORD;
  typedef         uint16_t WORD;
  typedef         uint8_t  BYTE;
  
  typedef struct MSTJMP_FLOAT128
  {
      QWORD Part[2];
  } MSTJMP_FLOAT128;
  
  typedef struct JUMP_BUFFER
  {
      QWORD Frame0;
      QWORD Rbx0;
      QWORD Rsp0;
      QWORD Rbp0;
      QWORD Rsi0;
      QWORD Rdi0;
      QWORD R120;
      QWORD R130;
      QWORD R140;
      QWORD R150;
      QWORD Rip0;
      DWORD MxCsr4;
      WORD FpCsr2;
      WORD Spare2;
      struct MSTJMP_FLOAT128 Xmm6x;
      struct MSTJMP_FLOAT128 Xmm7x;
      struct MSTJMP_FLOAT128 Xmm8x;
      struct MSTJMP_FLOAT128 Xmm9x;
      struct MSTJMP_FLOAT128 Xmm10x;
      struct MSTJMP_FLOAT128 Xmm11x;
      struct MSTJMP_FLOAT128 Xmm12x;
      struct MSTJMP_FLOAT128 Xmm13x;
      struct MSTJMP_FLOAT128 Xmm14x;
      struct MSTJMP_FLOAT128 Xmm15x;
  } JUMP_BUFFER;
  
  int main() {
  
      struct JUMP_BUFFER jumpbuffer;
  
     setjmp(&amp;jumpbuffer, 0);
  
      return 0;
  }
  </code></pre>
  <p>The disassembly for setjmp() call is</p>
  <pre><code>setjmp(&amp;jumpbuffer, 0);
  00007FF641B51019  xor         edx,edx  
  00007FF641B5101B  lea         rcx,[jumpbuffer]  
  00007FF641B51020  call        __intrinsic_setjmp (07FF641B51C20h)  
  </code></pre>
  <p>which leads to the setjmp() code</p>
  <pre><code>--- d:\a01\_work\2\s\src\vctools\crt\vcruntime\src\eh\amd64\setjmp.asm ---------
  00007FF82B6F0300  mov         qword ptr [rcx],rdx  
  00007FF82B6F0303  mov         qword ptr [rcx+8],rbx  
  00007FF82B6F0307  mov         qword ptr [rcx+18h],rbp  
  </code></pre>
  <p>so everything is functioning correctly without any errors because windows is using a C-runtime intrinsic within setjmp.asm</p>
  <p>However, under linux, it generates an error:</p>
  <blockquote>
  <p>error: macro &quot;setjmp&quot; passed 2 arguments, but takes just 1</p>
  </blockquote>
  <p>Google'ing found this code snippet:</p>
  <pre><code>#if defined(_WIN64)
  /* On w64, setjmp is implemented by _setjmp which needs a second parameter.
   * If this parameter is NULL, longjump does no stack unwinding.
   * That is what we need for QEMU. Passing the value of register rsp (default)
   * lets longjmp try a stack unwinding which will crash with generated code. */
  # undef setjmp
  # define setjmp(env) _setjmp(env, NULL)
  #endif
  </code></pre>
  <p>To sum up, windows can take 2 args:</p>
  <pre><code>setjmp(&amp;jumpbuffer, 0);
  </code></pre>
  <p>and linux can take 1 arg:</p>
  <pre><code>setjmp(&amp;jumpbuffer);
  </code></pre>
  <p>To verify that linux likes that setjmp, I traced with <strong>gdb</strong> as follows:</p>
  <p><a href="https://i.stack.imgur.com/7TfuA.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/7TfuA.png" alt="linux_gdb" /></a></p>