<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Possible thread stack size problem on macOS with deep recursion]]></title><description><![CDATA[<h3>Possible thread stack size problem on macOS with deep recursion</h3>
<p dir="auto">Hello,</p>
<p dir="auto">I am the co-developer of FET, a Qt-based timetabling application, and I am investigating an intermittent crash reported by a macOS user.</p>
<p dir="auto">The application performs timetable generation in several worker threads. Currently these threads are created using <code>std::thread</code>, for example:</p>
<pre><code class="language-cpp">std::thread([t]{
    timetablingThreads[t].startGenerating();
}).detach();
</code></pre>
<p dir="auto">The generation algorithm contains a large recursive function, <code>Generate::randomSwap()</code>. The recursion depth is explicitly limited to 14.</p>
<p dir="auto">The user reported that with multiple generation threads the application sometimes crashes on macOS, while single-thread generation seems stable. The original macOS crash report showed memory allocation functions such as <code>QArrayData::allocate()</code> / <code>malloc()</code>, which initially made me suspect heap corruption.</p>
<p dir="auto">To investigate this I built FET with AddressSanitizer:</p>
<pre><code class="language-text">-O1
-g
-fsanitize=address
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
</code></pre>
<p dir="auto">and linked with:</p>
<pre><code class="language-text">-fsanitize=address
</code></pre>
<p dir="auto">ASan is definitely active.</p>
<p dir="auto">With ASan, the problem becomes reproducible almost immediately. ASan reports:</p>
<pre><code class="language-text">ERROR: AddressSanitizer: stack-overflow
</code></pre>
<p dir="auto">The worker-thread stack reported by ASan is approximately:</p>
<pre><code class="language-text">size 0x83000
</code></pre>
<p dir="auto">so roughly 524 KiB.</p>
<p dir="auto">The stack trace contains many recursive calls like:</p>
<pre><code class="language-text">Generate::randomSwap(int, int) generate.cpp:38619
Generate::randomSwap(int, int) generate.cpp:38619
...
</code></pre>
<p dir="auto">until ASan reports the stack overflow.</p>
<p dir="auto">As a test, I replaced the <code>std::thread</code> creation with <code>QThread::create()</code> and explicitly set a larger stack:</p>
<pre><code class="language-cpp">QThread* thread = QThread::create([t]{
    timetablingThreads[t].startGenerating();
});

thread-&gt;setStackSize(16 * 1024 * 1024);

connect(thread, &amp;QThread::finished,
        thread, &amp;QObject::deleteLater);

thread-&gt;start();
</code></pre>
<p dir="auto">With this change, the immediate ASan stack overflow disappears and generation continues normally for much longer.</p>
<p dir="auto">So my questions are:</p>
<ol>
<li>Does this look like a normal consequence of the relatively small default worker-thread stack on macOS, especially with ASan and a large recursive function?</li>
<li>Would explicitly increasing the thread stack size be the appropriate permanent fix for this kind of application?</li>
<li>Is there anything Qt-specific I should consider when using <code>QThread::setStackSize()</code> on macOS?</li>
<li>Could the original non-ASan crash, which appeared inside <code>malloc()</code> / <code>QArrayData::allocate()</code>, plausibly have been another manifestation of stack exhaustion, or should I continue looking for an independent heap corruption/data race?</li>
<li>Is 16 MiB a reasonable stack size here, or would you recommend another approach?</li>
</ol>
<p dir="auto">Environment:</p>
<ul>
<li>macOS on Apple Silicon</li>
<li>Qt 6.11.x</li>
<li>Clang / Xcode</li>
<li>C++17</li>
<li>FET timetable generator</li>
<li>up to 4 generation threads in the reported case</li>
<li>recursion depth limited to 14</li>
</ul>
<p dir="auto">I would appreciate any advice on whether increasing the worker-thread stack is the correct solution, or whether there is something else I should investigate before making this change permanent.</p>
]]></description><link>https://forum.qt.io/topic/165088/possible-thread-stack-size-problem-on-macos-with-deep-recursion</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 23:42:53 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/165088.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 12 Sep 2026 09:30:18 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Possible thread stack size problem on macOS with deep recursion on Mon, 14 Sep 2026 06:28:25 GMT]]></title><description><![CDATA[<p dir="auto">On the one hand you are saying that you have restricted the recursion depth to 14 levels, but on the other hand you are saying you have a stack overflow. This does not make sense unless you have really huge stack frames (any arrays on the stack?). Or your actual recursion depths is much deeper than 14 levels.</p>
<p dir="auto">It is quite likely that the stack overflow is the real problem and <code>malloc</code> doesn't have to do anything with it. For now, I would stop looking elsewhere.</p>
<p dir="auto">Setting a larger stack size certainly seems to help. Somebody mentioned that Linux stack size is 8MB, so you could even just go with 8MB (instead of 16MB) if your software works on Linux. However, this is not a permanent fix! Over time people will run larger and larger problems. You'll eventually run out of stack space on all operating systems, not just macOS. The best solution might be to rewrite your recursive algorithm with a loop. (This is technically also not a permanent solution, but the only restriction is not enough RAM and there is nothing you can do about it in software.)</p>
]]></description><link>https://forum.qt.io/post/840138</link><guid isPermaLink="true">https://forum.qt.io/post/840138</guid><dc:creator><![CDATA[SimonSchroeder]]></dc:creator><pubDate>Mon, 14 Sep 2026 06:28:25 GMT</pubDate></item><item><title><![CDATA[Reply to Possible thread stack size problem on macOS with deep recursion on Sat, 12 Sep 2026 19:35:47 GMT]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto">I agree with <a class="plugin-mentions-user plugin-mentions-a" href="/user/igkh">@<bdi>IgKh</bdi></a> about the safety of changing the stack size. It's also part of using the system as designed. You simply require more of it and can request so.<br />
You can find more information <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/10000057i-CH15-SW2" target="_blank" rel="noopener noreferrer nofollow ugc">in the Apple developer documentation.</a></p>
]]></description><link>https://forum.qt.io/post/840119</link><guid isPermaLink="true">https://forum.qt.io/post/840119</guid><dc:creator><![CDATA[SGaist]]></dc:creator><pubDate>Sat, 12 Sep 2026 19:35:47 GMT</pubDate></item><item><title><![CDATA[Reply to Possible thread stack size problem on macOS with deep recursion on Sat, 12 Sep 2026 12:31:01 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/volker_75">@<bdi>Volker_75</bdi></a> said in <a href="/post/840115">Possible thread stack size problem on macOS with deep recursion</a>:</p>
<blockquote>
<p dir="auto">chat-gpt sadly refuse to answer several of my questions because of "cyber security issues".</p>
</blockquote>
<p dir="auto">Pretty funny, but I can see why it might trigger the guardrails. Stack smashing attacks (e.g. trying to purposefully overflow the stack) are a crude but common type of attack. You can perhaps reframe the conversation to analyzing why the macOS version consumes more stack space than the Linux version - if it is indeed what you think is happening.</p>
<p dir="auto">I don't think valgrind is very reliable on macOS though? Its hard to see through the black magic going inside the Objective C runtime (and make no mistake, even if your application's code is 100% C++, you ARE using objective C behind the scenes). You should try to use the Xcode instruments to measure memory usage.</p>
<p dir="auto">If you can make a minimal reproducing example that overflows the stack on macOS but not on Linux (with the same stack size), post it and I can try to debug it as well.</p>
]]></description><link>https://forum.qt.io/post/840116</link><guid isPermaLink="true">https://forum.qt.io/post/840116</guid><dc:creator><![CDATA[IgKh]]></dc:creator><pubDate>Sat, 12 Sep 2026 12:31:01 GMT</pubDate></item><item><title><![CDATA[Reply to Possible thread stack size problem on macOS with deep recursion on Sat, 12 Sep 2026 12:18:54 GMT]]></title><description><![CDATA[<p dir="auto">Thank you for answering. I already tried to measure a lot and investigate. The strange thing is, that the memory usage under Linux looks much smaller (measures with  "valgrind -v --tool=massif --stacks=yes ./fet" and discussing the issue with AI is difficult. chat-gpt sadly refuse to answer several of my questions because of "cyber security issues". So if you (other guys) have more idea, please let me know.</p>
]]></description><link>https://forum.qt.io/post/840115</link><guid isPermaLink="true">https://forum.qt.io/post/840115</guid><dc:creator><![CDATA[Volker_75]]></dc:creator><pubDate>Sat, 12 Sep 2026 12:18:54 GMT</pubDate></item><item><title><![CDATA[Reply to Possible thread stack size problem on macOS with deep recursion on Sat, 12 Sep 2026 12:06:57 GMT]]></title><description><![CDATA[<p dir="auto">Welcome to the forum!</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/volker_75">@<bdi>Volker_75</bdi></a> said in <a href="/post/840112">Possible thread stack size problem on macOS with deep recursion</a>:</p>
<blockquote>
<p dir="auto">so roughly 524 KiB.</p>
</blockquote>
<p dir="auto">Yes, this tracks. The default stack size for threads created via the pthreads APIs in macOS is 512 KB, which is way smaller than on other Unix-like systems (e.g. on Linux secondary stacks are 8 MB by default). This is not the only way in which Apple's pthreads implementation is different. I don't like it all that much.</p>
<p dir="auto">I think that in macOS distributing jobs to a pool is typically done with the GCD (Grand Central Dispatch) API, but I suppose you don't really want to use non-portable APIs.</p>
<p dir="auto">I'm not aware of any particular specific issues with increasing the stack size up from the default. Non specific concerns are the usual ones: allocating unbounded amount of stack data is generally frowned upon, and large stacks can exhaust address space (not really a problem if the number of threads is static). So it is really up to your own design constraints and preferences.</p>
]]></description><link>https://forum.qt.io/post/840114</link><guid isPermaLink="true">https://forum.qt.io/post/840114</guid><dc:creator><![CDATA[IgKh]]></dc:creator><pubDate>Sat, 12 Sep 2026 12:06:57 GMT</pubDate></item></channel></rss>