Problem Overview
The exception code C0000005 ACCESS_VIOLATION raised inside the WinCC scripting runtime terminates script.exe on a WinCC client or server. The crash text is written to <WinCC_Project>\Scripts\log\script.log and to the Windows Application event log. After the first fault, all global C-scripts stop executing on the affected machine. The image is processed in the background service script.exe, which is launched by the WinCC Runtime as soon as the first @-script is triggered. When the service crashes it is restarted by the WinCC runtime, but the fault re-occurs within seconds whenever the triggering event fires again, producing a tight loop of exceptions until the project is reloaded or the action is removed.
The problem has been observed on:
- WinCC V6.2 SP3 (legacy release, still installed on many operating stations)
- WinCC V7.0 SP1, SP2 and SP3 (RT and RT64 client builds)
- WinCC V7.2, V7.3 and V7.4 (when the project was originally migrated from V6.2/V7.0 and the legacy C-action code is still present)
The crash is independent of the HMI station role: it occurs on single-user stations, on WinCC servers running the project as a server, and on WinCC clients that connect to a remote server. The error is non-deterministic: the same project can run for hours or days before the first fault, then crash repeatedly.
Symptoms
Engineers typically see one or more of the following:
- The WinCC runtime goes into a "Not Ready" state. Pictures stay open but no values update, and no user input is processed by actions.
- APCdiag (Action Performance Diagnosis) shows the action that triggered the fault as "aborted".
- The Windows Event Viewer (Application log) records an Error of source
Application Errorand faulting modulescript.exe, version range typical of the installed WinCC build. - Subsequent script calls are dispatched to a freshly-started
script.exeinstance which then crashes again at the next trigger. - Tag logging and alarms keep running because they use
CCAlgRtServer.exeandCCMsgServer.exe, notscript.exe. Only the action layer is broken.
C0000005 from WinCC is not a Windows fault - it is generated by the C runtime of the WinCC scripting engine. The exception is wrapped by the WinCC error reporter and written verbatim to script.log. Treat the file as the authoritative crash dump, not the Windows event log.Exception Code Reference
The Windows structured exception code 0xC0000005 is defined as EXCEPTION_ACCESS_VIOLATION. The exception is raised when a thread attempts to read from, write to, or execute a virtual address for which it has no permission under the current process state. In the WinCC context the access is almost always a read or write through a stale pointer obtained from a tag handle, a temporary string buffer, or a freed object.
| Field | Value in the script.log | Meaning |
|---|---|---|
| Exception Code | 0xC0000005 | EXCEPTION_ACCESS_VIOLATION |
| Faulting Address | 0x7C9109F9 (ntdll) 0x100413CB (AKTSTEU) 0x1004171D (AKTSTEU) |
Address where the thread faulted |
| CS:EIP | 001B:7C9109F9 | Code segment : Instruction pointer |
| DS / ES | 0023 | Default user-mode data segment |
| SS:ESP | 0023:0353FD1C | Stack segment : stack pointer |
| Flags | 00010246 | EFLAGS at the time of fault |
For a Microsoft overview of the C0000005 access violation class see the official Microsoft Learn Inside C0000005 reference.
Root Cause
The crash has two distinct signatures. Both originate from the C-action interpreter of WinCC, but they are triggered by different patterns.
Signature A - wcsncpy inside SCSIVA~2.DLL
The call stack shows:
ntdll.dll!wcsncpy+0x49A
ntdll.dll!wcsncpy+0x2CD
msvcrt.dll!free+0xCD
SCSIVA~2.DLL!0x00008ED0
SCSIVA~2.DLL!0x00008389
SCSIVA~2.DLL!0x000055FF
SCSIVA~2.DLL!0x00007EEF
CThreadSafeObject::Release+0x3F
CThreadExecuteCall::~CThreadExecuteCall+0x7C
CThreadExecuteCall::operator=+0xFD
CThreadSafeObject::Release+0x3F
CAsyncCallList::OnMessage+0x62
CThread::OnRun+0x2E
CThread::OnExitInstance+0x44
msvcrt.dll!endthreadex+0x44
msvcrt.dll!endthreadex+0xD8
kernel32.dll!GetModuleFileNameA+0x1B4
SCSIVA~2.DLL is the Siemens ACE (ActiveX Control Embedding) helper that exposes OLE Automation / DCOM interfaces from CCScript.exe to the C-action runtime. The combination of wcsncpy called from free indicates a use-after-free in the lifetime management of an ACE object. WinCC allocates a temporary BSTR or wide-string buffer to pass a tag value to a C action, hands the buffer to the action, and the action returns a value that the runtime is supposed to free. If the value is freed by both the action and the runtime, or freed once with the wrong allocator, free() walks an invalid heap block and the second free is performed inside wcsncpy, which copies from a dangling pointer.
Signature B - AKTSTEU.dll GetValueBuffer
The call stack shows:
AKTSTEU.dll!0x000403CB
AKTSTEU.dll!GetValueBuffer+0x1EF2
Ordinal3180+0x10E
msvcrt.dll!endthreadex+0x44
msvcrt.dll!endthreadex+0xD8
kernel32.dll!GetModuleFileNameA+0x1B4
or
AKTSTEU.dll!0x0004071D
AKTSTEU.dll!GetValueBuffer+0x1EBF
Ordinal3180+0x10E
...
AKTSTEU.dll is the WinCC action control DLL. It implements the action scheduler, the trigger evaluation engine, and the bridge between a tag event and the C-action compiler output. GetValueBuffer is the function that reads the current value of the trigger tag at the moment the action fires. The crash at offset 0x000403CB with ECX = 0x00000000 and EDX = 0x00000014 is a NULL pointer dereference on the tag's internal value buffer, which means the trigger tag was deleted, renamed, or had its data type changed after the action was compiled.
Both signatures share one common trigger: a C action with a timer trigger, a tag trigger on a non-existent tag, or an action that has been compiled against an older picture tree and is now being re-dispatched after a project re-import.
Why Timer-Based C-Scripts Trigger the Fault
A WinCC C-action can be triggered by:
- A tag change (standard pattern, lowest risk)
- A picture open or picture change event
- A keyboard or mouse event
- A timer event (cyclic trigger)
- Hotkey or "once" event
The timer trigger is the most common root cause of C0000005. In a default WinCC V6.2 / V7.0 install, the C action runtime is single-threaded per project, but the WinCC picture runtime is multi-threaded. When a C action is triggered by a 1-second timer, the action is dispatched once per second, but each dispatch allocates a value buffer, compiles the return type, and frees both the input and the output buffer. If the C action contains a string assignment (char* or BSTR) inside a hot path, the buffer lifetime is short enough that a previously freed block is reused by the allocator and re-freed at the next cycle. The result is the free+0xCD crash inside wcsncpy.
When the same logic is moved to a tag-change trigger, the dispatch rate drops to the actual change rate of the tag, the lifetime of the buffer is the time between two real changes (typically hundreds of milliseconds or more), and the allocator does not return the freed block to a fresh allocation, so the use-after-free never occurs. This is the empirical workaround reported in the field: replacing a 1-second timer trigger with a tag-change trigger eliminates the fault immediately.
Diagnostic Procedure
-
Capture the crash text. Open the project path
Copy the last three exception blocks. The first word afterC:\Program Files (x86)\Siemens\WinCC\WinCCProjects\<project>\Scripts\log\script.logFAULTING MODULE:identifies the signature:-
ntdll.dll+wcsncpy= Signature A (use-after-free in ACE) -
AKTSTEU.dll+GetValueBuffer= Signature B (stale tag handle)
-
-
Enable ApDiag logging. ApDiag is shipped with WinCC V6.2 and later and is located in the WinCC installation directory. Open a WinCC project context and run
Set the filter to capture all actions, click Start Trace, and reproduce the crash. ApDiag writes the action name, the trigger type, the trigger tag, the dispatch time, and the return value. The last action in the trace is the one that faulted.Start > SIMATIC > WinCC > Tools > ApDiag.exe - List all global C actions and their triggers. In the WinCC Explorer, expand Global Script > C-Editor. For every action, note the trigger type, the trigger tag (if any), the picture it belongs to, and the last modification date. Sort by trigger type and identify every action with a timer trigger.
- Compare the trigger tag with the tag database. For every C action with a tag trigger, open the tag in the WinCC Tag Management. If the tag no longer exists, the trigger field references a deleted object and the action will fault the next time it fires.
-
Check the project's data type changes. If a tag was changed from
BOOLtoWORDor fromFLOATtoDOUBLE, the compiled action contains a call to a typed accessor that no longer matches the new type. The WinCC compiler does not always re-emit the call, so the action keeps the old accessor and faults insideGetValueBuffer. -
Inspect the picture tree. If a C action is attached to a picture, check that the picture file (PDL) still exists in the project's
Graficdirectory. Renaming a picture without re-binding the action leaves the action pointing to a non-existent picture object, and the first dispatch re-allocates an invalid pointer.
Step-by-Step Resolution
Step 1 - Stop the runtime
Close the WinCC runtime on the affected station. Confirm that script.exe is no longer running in Task Manager. Make a full backup of the project directory, including the project database, the Grafic directory, the Scripts directory, and the Library directory.
Step 2 - Remove the timer trigger
Open the action that was last listed in ApDiag, change the trigger from Standard cycle 1s (or any cyclic trigger) to a Tag trigger. Pick a tag that already changes at least every few seconds. If no suitable tag exists, create a dummy internal tag and write to it from a separate, low-priority VBScript that uses HMIRuntime.Tags("MyHeartbeat").Write in a 5-second loop. Do not start a C action with a 1-second cycle - use 5 seconds or longer if a cyclic trigger is unavoidable.
Step 3 - Repair stale tag references
For every action that uses a tag trigger, confirm the tag exists, has the same data type, and has the same address. If a tag has been renamed, update the action and recompile with File > Compile All in the C-Editor. If a tag has been deleted, replace it with a valid tag or disable the action.
Step 4 - Eliminate string manipulation in hot paths
C actions that perform strcpy, wcscpy, memcpy, or sprintf on a tag value are the highest-risk operations. Replace them with the WinCC-supplied string helpers:
// Instead of strcpy, use the safe wrapper provided by the WinCC API
const char* src = GetTagChar(lpszPictureName, "TagName");
char dest[256];
strncpy(dest, src ? src : "", sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';
SetTagChar(lpszPictureName, "DestTag", dest);
The same pattern applies to GetTagFloat, SetTagFloat, GetTagWord, and the typed accessors. Always bound the destination buffer and always check the return pointer before copying.
Step 5 - Recompile and re-link
From the C-Editor, run File > Compile All, then File > Link All. If the C-Editor reports a linking error against apsvar.lib or akttapi.lib, the project has a corrupt action cache. Close the project, delete the generated *.c and *.obj files in the ScriptLib directory, reopen the project, and recompile.
Step 6 - Install the latest Hotfix
Apply the latest WinCC V7.x hotfix from the Siemens Industry Online Support portal. The relevant hotfix bundles for C0000005 in script.exe are:
| WinCC Version | Hotfix / Patch | Notes |
|---|---|---|
| V6.2 SP3 | WinCC V6.2 SP3 Hotfix 14 (and later) | Includes the ACE/ScSiva lifetime fix |
| V7.0 SP3 | WinCC V7.0 SP3 Hotfix 11 (and later) | Fixes AKTSTEU tag-handle invalidation |
| V7.2 | WinCC V7.2 Upd 1 + Hotfix 6 | Replaces the legacy string allocator |
| V7.3 | WinCC V7.3 Upd 1 + Hotfix 4 | Replaces the legacy string allocator |
| V7.4 SP1 | WinCC V7.4 SP1 Upd 1 | Default already contains the fix |
Download from the Siemens Industry Online Support portal, search for entry ID 109757946 ("Why does the script error 'C0000005 ACCESS_VIOLATION' appear in the script.log?") and follow the attached hotfixes.
Verification
After the changes are applied, verify the fix in five steps:
- Start the WinCC runtime and let it run for 30 minutes with the previous trigger conditions. Confirm that
script.logdoes not grow. - Open ApDiag and confirm that the action that was last listed in the previous crash trace is no longer aborted.
- Watch the Windows Application event log. There must be no
Application Errorwith faulting modulescript.exefor at least 24 hours of continuous runtime. - Use
tasklist /fi "imagename eq script.exe"to confirm that thescript.exePID does not change every few seconds. A stable PID means the process is no longer being restarted. - Force a hot reload: close the runtime, reopen it, and confirm that all actions fire without exception for the first hour of operation.
Troubleshooting Matrix
| Symptom | Likely Cause | Action |
|---|---|---|
Stack points to wcsncpy + SCSIVA~2.DLL
|
Use-after-free in ACE string lifetime | Install WinCC hotfix, remove timer triggers, recompile |
Stack points to AKTSTEU.dll!GetValueBuffer
|
Stale tag handle (renamed/deleted/changed type) | Verify the tag exists, fix the data type, recompile |
| ECX = 0x00000000 in AKTSTEU crash | NULL tag value buffer | Check the tag is online and the PLC connection is up |
| EDX contains ASCII text such as 0x004F0044 | Buffer interpreted as DWORD when it is a string | Re-bind the tag with the correct data type |
| ECX = 0x69617254 ("Tari" in ASCII) | Tag name read past end of buffer | Tag name is empty - rename the tag and re-link the action |
| Crashes occur at the same time of day | External scheduler (Task Scheduler, antivirus scan) | Disable scheduled tasks that scan the WinCC directories |
| Crashes occur only on a redundant standby server | Standby receives no tag updates, buffer is reused | Use tag-change trigger, not timer trigger |
| Crashes occur after project re-import from V6.2 to V7.x | Generated C code references old picture object IDs | Re-create the actions in the new project rather than re-importing |
Long-Term Prevention
- Avoid timer-based C actions. Use tag-change triggers whenever possible. If a periodic refresh is required, use a VBScript that writes a single internal tag, and attach the C action to that tag with a 5-second or longer cycle.
-
Centralize the trigger tags. Create a set of internal tags such as
Heartbeat_1s,Heartbeat_10s, andHeartbeat_1minin the internal tag list, and reference them from every action. Never use a raw process tag as a trigger for a complex C action. -
Version-control the C actions. Export the global C actions as
*.pasfiles (or the*.c/*.hsource if the C-Editor was used) to a source-control system. A diff between two project versions will show every tag rename and every type change, and lets you spot the actions that have become stale. -
Keep WinCC current. Apply the latest hotfix bundle for the installed major version. Siemens releases hotfixes for the
C0000005issue on a regular basis and the newest hotfix supersedes the previous ones. -
Monitor the runtime. Use the
CCDiagnostic.exetool that ships with WinCC V7.x to monitorscript.exe. A restart ofscript.exemore than once per hour is a strong indicator of a recurring access violation, even if the exception text has not yet been written toscript.log. -
Exclude WinCC directories from antivirus scans. Real-time antivirus scanning of the project directory, the script library, and the WinCC bin directory can lock DLLs at the moment
script.exetries to load them and produce a delayedC0000005at the next symbol resolution. Add the project path,C:\Program Files (x86)\Siemens\WinCC, and the project database path to the antivirus exclusion list.
ApDiag Field Reference
ApDiag is the Application and Process Diagnosis tool for WinCC scripts. The most useful controls for this fault are:
| Control | Function |
|---|---|
| Action list | Lists every C action and its current state (running, aborted, completed) |
| Trace filter | Filters the trace by action name, trigger type, tag name, or picture name |
| Stack trace window | Shows the function calls that were active when the action was dispatched |
| Counter panel | Displays the number of dispatches per action since the trace was started; a counter that stops incrementing is a sign that the action is stuck |
| Tag value window | Shows the value of the trigger tag at the moment the action fired |
ApDiag is started from the WinCC project context. The trace files are written to <project>\Scripts\log\apdiag.log and are not deleted when the runtime is closed. Compare the latest trace with a known-good trace from a reference project to find the action that diverges.
Heap and Memory Model Notes
The Windows C runtime used by WinCC V6.2 / V7.0 SP3 is the static msvcrt.dll with the standard malloc / free allocator. The C-action interpreter allocates a value buffer for every call to a tag accessor, hands the buffer to the user code, and frees the buffer on return. The buffer size is determined by the data type of the tag:
| Tag Data Type | Buffer Size (bytes) | Access Function |
|---|---|---|
| BOOL | 1 | GetTagBit |
| SINT / USINT | 1 | GetTagByte |
| INT / UINT / WORD | 2 | GetTagWord |
| DINT / UDINT / DWORD | 4 | GetTagDWord |
| REAL / FLOAT | 4 | GetTagFloat |
| DOUBLE / LREAL | 8 | GetTagDouble |
| CHAR (raw text) | 1 to 256 | GetTagChar |
| STRING (WinCC text ref) | 256 | GetTagChar |
If a C action requests a different size than the one the tag actually has (for example, a request for a DWORD on a tag that has been changed to REAL), the buffer is the right size for the new type, but the action code reads it as the old type. The first two bytes of the buffer will be the lower half of the IEEE-754 single-precision value, and the next two bytes will be the upper half. When the action passes this buffer to a string function, the string function reads the raw bytes and may overrun the buffer if the upper bytes do not contain a zero terminator within the expected length. The wcsncpy crash is the most common result.
Why a 1-Second Timer Is the Worst Case
On a 1-second timer, the action is dispatched 86,400 times per day. Each dispatch allocates a value buffer of typically 4 to 256 bytes. Over 24 hours the runtime allocates between 1.3 MB and 86 MB of short-lived buffers through the same allocator. The Windows low-fragmentation heap (LFH) will reuse the freed blocks aggressively, and a use-after-free that is harmless on a low-frequency trigger becomes a crash on a 1-second trigger. The empirical rule from Siemens support is: do not use a timer trigger faster than 5 seconds for any C action that touches a string or a tag value. For pure housekeeping (counters, blinkers, heartbeats), use VBScript with the HMIRuntime object instead of C.
Restoring a Corrupt Project
If the project has been corrupted by a chain of C0000005 events, follow the recovery procedure:
- Stop the WinCC runtime and the WinCC Server service.
- Restore the most recent backup of the project directory. The backup must include the
Grafic,Library, andScriptssubdirectories as well as the project database files. - If no backup is available, use the Project Duplicator in the WinCC Explorer to clone the project to a new path, then re-import the picture tree from the source project one picture at a time.
- Re-link the actions one at a time. Re-link and re-test the project after every action is added. The action that triggers the crash is the one that contains the stale reference.
- Once the project runs cleanly, deploy the fix to the production server.
script.exe in an inconsistent state and produce a second, harder-to-diagnose fault on the next trigger.FAQ
What does the WinCC exception code C0000005 ACCESS_VIOLATION mean?
It is the Windows structured exception code for EXCEPTION_ACCESS_VIOLATION, raised when the WinCC scripting engine reads or writes a memory address for which it has no permission. In WinCC it almost always means a stale tag handle, a freed string buffer, or a NULL pointer inside AKTSTEU.dll's tag value accessor.
Where do I find the script.log file for a WinCC C0000005 crash?
The file is at <project_path>\Scripts\log\script.log on the station where the runtime is running. The path is usually C:\Program Files (x86)\Siemens\WinCC\WinCCProjects\<project>\Scripts\log\script.log.
Can a 1-second timer trigger cause the C0000005 crash in WinCC?
Yes. A 1-second timer trigger on a C action is the most common cause of the C0000005 crash. The action is dispatched 86,400 times per day, the value buffer is allocated and freed on every dispatch, and the low-fragmentation heap reuses the freed block, which produces a use-after-free inside wcsncpy. Replace the timer trigger with a tag-change trigger, or increase the timer cycle to 5 seconds or longer.
Which WinCC hotfix resolves the script.exe C0000005 crash?
The hotfix depends on the installed WinCC major version: WinCC V6.2 SP3 Hotfix 14, WinCC V7.0 SP3 Hotfix 11, WinCC V7.2 Upd 1 + Hotfix 6, and WinCC V7.3 Upd 1 + Hotfix 4. The latest hotfix for the installed major version should be applied. Hotfixes are available from the Siemens Industry Online Support portal.
How do I run ApDiag to find the action that triggered the fault?
Start the WinCC runtime, then start ApDiag.exe from the WinCC Tools menu. Click Start Trace, let the runtime run until the next crash, then open the trace. The last action in the trace is the one that faulted. Compare its name and trigger type with the action list in the WinCC Explorer to find the source code that needs to be fixed.
Will VBScript actions also crash with C0000005?
VBScript actions run in a separate interpreter (the VBScript runtime from Windows Script Host) and do not use AKTSTEU.dll. The C0000005 access violation described in this article is specific to C actions. VBScript actions have their own error model and report errors through the WinCC diagnostic log with a VBScript error number, not a Windows exception code.
Is the C0000005 crash in script.exe a Windows fault or a WinCC fault?
It is a WinCC fault surfaced through the Windows structured exception handling. The exception is raised by the C runtime that backs the WinCC C action interpreter, not by Windows itself. The Windows event log only records the consequence; the script.log file contains the root cause.