I’ve been advised (via the C12 newsgroup) to repost this here…
It would be appreciated if someone from SV could look at problem tracker #43507. This will prevent our C12 adoption and it’s very likely other Clarion
users will be impacted. The code to reproduce (see below) couldn’t really be
more trivial. It leaks memory on each timer event (with this example, approx.
4kb every 5 seconds). The higher the numeric TIMER attribute value the less
obvious, but it still leaks.
PROGRAM
MAP
END
W WINDOW('Test'),SYSTEM,TIMER(1).
CODE
OPEN(W)
ACCEPT.
CLOSE(W)
The program tracks the process’s Private Bytes (same figure Task Manager shows). It reports two things: Total growth — how much that has risen since the app started — and Avg/tick — the average number of bytes leaked per timer event. The per‑event average is the key number, because raw Private Bytes rises in chunky steps (Windows commits memory in blocks), so the average is what reveals the true, steady leak rate underneath.
If it has been around since C6 days, then I’m thinking we would have noticed by now.
Which makes me think perhaps the example is too simple. Ie something else (which is now missing) causes the leak not to happen. I’m going to test a bit more.
I think this makes it a bit harder to see - the extra work you’re doing on each tick means fewer timer events can be processed. It would probably be better to only update the screen every 10 ticks or so. In addition, I would expect some growth initially, but that should settle down. This is what happens when I run your version in C9 (total growth eventually steady at 60KB). In C12 total growth is now 1852KB. I’d be very surprised if this was in 6.3 but I don’t have that to test with. It’s definitely not in C9.
Incidentally, the memory is not freed when the window is closed. But it is just before the process exits (it might be freed on a per-thread basis, I haven’t tried - but that could explain why this seems to have gone unnoticed). If you leave the app running for long enough and then close it, you’ll see the process hangs around for quite a while churning CPU as it frees all the thousands of small allocations it’s made.
In Clarion11.1.13855 I’m not seeing any growth either.
There’s some on the first tick, then nothing. So not seeing the problem there. Will try now on C12.
update: I’m also not seeing any problem on Clarion 12.0.0.14000.
So either the issue is specific to some build of Clarion 12, or there’s something else in play. I’m at 15000 ticks, and everything is stable. No memory growth.
15000 ticks is not really enough to see the issue (especially with Mark’s version). I think it’s easier to see with my original app. Just keep an eye on the ‘Working Set’ in Task Manager. There will be a little fluctuation from time-to-time but it will leak about 4KB every 5 seconds or so. Note the memory before going for lunch - by the time you get back it will probably have increased by 1-2MB.
I’m using 12.0.0.14000. I haven’t tried any other version except C9 and the problem is not there.
I built a small instrumented version of the reproducer to measure what’s actually happening per timer event. It dynamically loads GetProcessMemoryInfo from psapi.dll (no import lib needed) and reads PrivateUsage — the same “Private Bytes” Task Manager shows — then reports total growth, a cumulative bytes/tick average, and net growth over a rolling 1000‑tick window.
On C12 (build 14000):
Private Bytes rises ~270 KB in the first few seconds, then plateaus.
Net growth over each rolling 1000‑tick window settles to 0 — it stops climbing.
The cumulative bytes/tick figure keeps decaying toward 0, which is the signature of a one‑time warm‑up cost (heap reserves, window/GDI resources, lazy RTL init), not an unbounded per‑event leak.
Total growth varies run to run (~270–490 KB) and doesn’t track the number of timer events — again inconsistent with a steady per‑tick leak.
I also drove the same work two other ways to separate “the timer” from “Clarion’s event loop” — a Win32 SetTimer callback that posts a Clarion event, and a raw TimerProc that does the work directly — and saw the same flat result.
So this is probably not a timer bug, and on my C12 build I can’t reproduce an unbounded leak at all — the early growth is bounded warm‑up. Apologies for the earlier misdiagnosis.
If anyone can get sustained growth (window growth staying positive across tens of thousands of ticks), please post your exact build and OS — that’s the data that would confirm a real defect.
The leak is tiny; around 12 bytes/tick. Your version of the app has a lot of ‘noise’ which makes it harder to see the problem (you have to keep it running much longer before it starts to drown out the ‘warm up cost’). I changed it to only update the screen every 100 ticks. After running for around 2 hours (give or take, not sure exactly when I started it) it’s done 350k ticks and ‘growth’ reports as 4276kb. Task Manager shows a working set of 18,980kb.
I have spent hours investigating this, going from a complex app that runs as a service and boiling it down to a trivial example (honestly, TIMER was the last place I thought to look!). But there is a bug here, you’ve just got to let the app run for longer to see it.
It should be noted that C9 starts off with a higher memory footprint. Running my original version, it takes around 10 minutes for the C12 exe to start using more memory than C9. There will be some fluctuation but after 20 minutes or so the leak will be clear with C12 using around 700-800kb more. I can’t post a screenshot, but after running both side-by-side for 40 minutes the working set for C9 is 14,204kb and for C12 it’s now up to 16,044kb.
yes, I’ve run it for several hours now an it has stabilised on leaking 12 bytes per event.
Clarion 12.0.14000
Update: It leaks 12 bytes per EVENT. All events contribute to this, not just event:Timer.
I used Event:User instead of Event:Timer and got the same effect.