How are these three words related? C++ is a language, LLVM is a compiler infrastructure. Cybersecurity is a whole different beast. Sometimes experienced engineers say that C++ is incompatible with the term “cybersecurity” and should be replaced with safer languages. We argue that this is not correct, and that C++ has an awesome future going forward. To explain why, let’s start with two small clarifications: what C++ was designed for, and what people usually mean when they call it “insecure”.
Table of Contents
The truth about C++ security
It’s true that C++ was not designed as a memory-safe language. Historically, performance, low-level control, and compatibility were prioritized, and many safety guarantees were left to the programmer.
The practical truth is simple: C++ can be used for security-sensitive software, but it is not safe by default. Safer C++ is achieved through consistency: limit unsafe patterns, prefer clear ownership (RAII), avoid ambiguous APIs, and treat untrusted input carefully. With that mindset, many of the most common C++ failure modes become less likely.
Now, with that baseline in mind, we can address the most common misconception people bring to this discussion.
The myth that C++ is not secure
The myth is that C++ is still not secure. In fact, C++ makes it easy to express both safe and unsafe designs. That flexibility is a feature – but it also means you can’t judge security from the language name alone.
When people argue about whether “C++ is secure”, they are often mixing two different questions: what the language permits in principle, and what a particular codebase actually does in practice. In other words, C++ security is less a property of the language itself and more a property of the subset you rely on, the idioms you allow, and the discipline with which the codebase is maintained.
C++ still carries the legacy of previous versions. It is still possible to compile (likely without a single change) code written in C. In most cases, it is also fairly easy to compile code written for older C++ standards, except for very rare and very old versions.
This means the legacy of C and older C++ is preserved with care. That sounds fantastic for users, yet the picture is not so bright for security researchers.
Still, legacy and security are not the same thing. To understand where problems actually come from, it helps to step back and look at the broader origins of security issues – many of which have little to do with C++ specifically.

What are the origins of C++ security issues?
Starting, or rather continuing, with the Therac-25 incident, the field of software engineering has been facing many challenges. One of the most important is security, which requires a lot of effort to address.
However, modern software engineering is even more complicated. Every industrial product has many dimensions, and all of them affect security.
There are several main origins of security issues. In this post, we will focus on the subset that we will return to later, when discussing C++ and compilers:
- Programming language choice. This is an important factor. However, it is worth noting that it is not always possible to make that choice for a specific product. For example, for an embedded device, it is often necessary to use C or C++ due to resource constraints. This limitation creates a chicken-and-egg problem in the ecosystem: the ecosystem is written in C/C++, and to use that ecosystem efficiently, it is still necessary to use C/C++.
- Lack of testing.
- Lack of verification.
Many other factors are just as important (process, documentation, dependencies, hardware, and more), but we will keep them out of scope here to avoid turning this article into a generic security checklist.
How does AI affect C++ security?
AI is a blessing and a curse. While it can automate many tasks and improve efficiency, it can also introduce new vulnerabilities and security risks. At the moment, code produced by AI should not be assumed to be safe, because AI can miss critical context and make confident but incorrect choices.
With those general origins in mind, we can now zoom back in and look at C++ specifically, and what “safer C++” tends to mean in practice.
C++ from a cybersecurity perspective

It is worth distinguishing between C and C++. It is also useful to distinguish between different styles of C++:
- “Full C++”, including all legacy and low-level features that mightn’t be compatible with the best practices.
- C++ used with a subset of features: only the best practices.
Why is this distinction important? C is a powerful language for systems development. It offers full control over memory and hardware, making it ideal for low-level programming tasks. With great power comes great responsibility, and C++ was created to address some of C’s problems – most notably the lack of memory safety:
- Any memory allocated within the program can be accessed by any part of the program, which can lead to security vulnerabilities and, consequently, data leaks.
- It is particularly easy to overflow or underflow buffers – a major source of security exploits.
- Threading mistakes are common.
- It is easy to leak memory.

Even though C++ is often called a superset of C, that is not entirely accurate. C++ includes nearly all C features, and using those features carries many of the same risks. Using only higher-level C++ features does not automatically eliminate them. A practical rule of thumb is to avoid direct memory management (raw pointers for ownership) and low-level operations unless you have a strong reason and clear safeguards.
Is C++ safe with that rule? In general, no. But the risks are significantly reduced if you follow it consistently.
Once you accept that C++ safety is largely about reducing error sources, it becomes easier to see why newer standards matter.
How do the new C++ standards help secure software?
New C++ language features reduce the amount of possible error sources.
- Contracts help build trust between function calls by specifying preconditions, postconditions, and invariants. This is akin to verifying program correctness, and it is an advanced yet conceptually simple technique.
- Const expressions eliminate runtime issues by moving them to compilation time.
- Object lifecycle changes make stricter rules for objects, remove hidden indirect casts, and eventually help get rid of Undefined Behavior.
- Concepts guarantee correctness of interfaces.
- Uninitialized data is now less common with the introduction of improved initialization rules, which has been a significant contributor to (in)security.
- Execution library helps manage asynchronous execution safely.
As you can see, new features improve C++ a lot, that’s why it is important to leverage new C++ features in your code.
What do we mean by undefined behaviour?
C++ is a language that suffers from undefined behavior. This ranges from relatively simple issues like signed integer overflow (the result of x + 1 > x is not guaranteed) to complex issues involving object lifetimes and uninitialized members.
Luckily, new C++ improves a lot regarding undefined behavior, slowly pushing this issue into the past.
Why can optimizations make software less secure?
Optimization is a key aspect of the modern compilation process. It reduces execution time by eliminating unnecessary constructs or computations that are constant, sometimes removing code entirely and freeing the memory used for it.
However, optimizations can also lead to unexpected behavior. For example, if the compiler assumes that a variable is not accessed concurrently, it may generate code that is not safe under multithreading. This can lead to data races, concurrency issues, or even infinite loops.
Historically, the quality of optimizations was entirely up to the developer, who could influence it with specific markup. The situation changes, and these days optimizations are often verified automatically by the compiler, ensuring that the generated code is safe and correct.
Runtime testing in C++ has significantly improved
Recently, many useful advancements in runtime testing/debugging have arrived in the C++ ecosystem.
1. Dynamic analysis and debugging tools became more sophisticated. There are several reversible debuggers available in the market, and they may roll back the execution of the program to a previous state, allowing developers to inspect the state of the program at that point in time.
2. Sanitizers are now mandatory in everyone’s toolchain. Memory errors, undefined behavior, and threading issues are now detected.
3. Fuzzing tools have become more useful and applicable to the real world.
This is one level of confidence. But the real power is when the code is not run.
What can I do to verify C++ security and memory safety?
Static analysis and verification are always significantly harder. It depends on what the user wants to achieve in the end – whether it is total correctness, the absence of obvious runtime errors, or just a high level of confidence in the code. Based on purpose, the selection of tools varies, but they form two significant groups that continue to improve.
1. Static analysis tools became dramatically better. They can detect more bugs and issues before they become vulnerabilities. LLVM, which we will cover later, became a de facto infrastructure for such analyses.
2. Real verification tools adopt new mathematical methods, such as abstract interpretation, satisfiability modulo theories, constrained Horn clause solvers, model checking, symbolic execution, etc. These methods reduce the complexity of verification, reduce the time to verify, and make verification more scalable.
This brings us naturally to the compiler ecosystem itself, and why LLVM is relevant in a security conversation.
What positive effect does the introduction of LLVM have on C++?
LLVM is a modular framework for building compilers and interpreters. It features a unified representation called LLVM IR and that can be compiled to machine code of virtually any architecture.
Ever since its introduction, LLVM has become an entry point for researchers. Almost any scientific paper on compilers mentions LLVM. Its practical impact is also hard to overestimate: nearly all new languages are built on top of LLVM, including Rust, and many older languages have switched from other code generators to LLVM. Delphi is among them.
More recently, the introduction of MLIR has brought a higher level of abstraction to the LLVM ecosystem by adding dialects for various domains and the ability to describe higher-level operations.
Clang is an LLVM-based compiler for C and C++. It is widely used in industry and has a large community. It is not just a top-tier compiler; it is also a powerful benchmark to compare against other compilers. The C++ toolchain around it is unique: it includes the LLDB debugger, fuzzing tools, static analysis tools, and much more.
While all of this is good… How is the fact of switching to LLVM useful to C++?
It is simple: more LLVM users in general means more developer focus, a more refined architecture, and a more stable implementation of the underlying compiler infrastructure. More users also means more LLVM features become available to C++ developers. And as more LLVM capabilities are exposed through LLVM/Clang-based tools, static analysis techniques and diagnostics improve. Over time, this contributes to safer C++ than it was several years ago.
Another approach to safer C++
Recently, the Fil-C, a new compiler based on LLVM, aimed at memory safety of C++, was introduced. It instruments all unsafe operations with dynamic checks designed to catch these problems. The first reports are quite promising, and we are excited to see how it evolves.
Stepping back from any single compiler or feature, there is also a broader ecosystem dynamic that affects security outcomes.
The community effect and cybersecurity
The infrastructure matters. While C++ is not the safest language, with the community it becomes safer, closing many gaps.
With greater visibility, it becomes harder to introduce a vulnerability and keep it undiscovered.
With more people testing the code and more users relying on these tools, fewer issues remain unfound.
Against that backdrop, it’s worth highlighting what this shift means in practice for Embarcadero and its users.
The benefits of C++ improvements for Embarcadero
We develop tools that help our customers build software faster – not only the compiler. As part of the community, we can focus on what matters most to our clients: customer-facing features.
That also means our tools benefit from improvements made by the community. Our latest C++ compiler, bcc64x, is a great step forward as it is based on LLVM/Clang, and it enables the use of many third-party tools, analyzers, sanitizers. It enables rapid application development, is more compatible with the recent C++ libraries, and is more secure by combining decades of Embarcadero’s experience with the experience of other companies.

Why not download a free trial of the latest C++Builder and try the great new features for yourself?
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition






