Why We Should Double-Check the AI Output: Claude Lies (AKA AI Hallucinations)

Another example showing how AI output should be carefully reviewed, and not accepted passively.

I was “discussing” with Claude about using #define guards vs. #pragma once for C++ header files. At some point, Claude wrote that:

If your library is only ever going to target modern mainstream compilers (which, realistically, is true for almost everyone today), plain #pragma once is fine and is what most modern C++ style guides (including Google’s and LLVM’s) now recommend by default.

I did remember that, last time I checked, Google’s C++ Style Guide required #define guards (not #pragma once) for header files. That is still true as of today (August 18th, 2026); quoting Google’s C++ Style Guide on this point:

All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.

So I made my point to Claude, and it replied apologizing for its error:

You’re right, and I apologize for the error. Looking at the actual page, Google’s C++ Style Guide explicitly requires #define guards, not #pragma once

This is another example showing how AI output cannot be 100% trusted, and should always be carefully reviewed.

Google's C++ Style Guide point on using #define guards for header files.
Google’s C++ Style Guide requiring #define guards for header files.

Claude AI wrongly stating that Google's C++ Style Guide recommends #pragma once, and its apologies after my correction.
An excerpt of my “discussion” with Claude AI on #define guards vs. #pragma once.

On AI Hallucinations

I briefly asked another AI (Gemini) about AI hallucinations (like the previous example with Claude), and it interestingly pointed out that:

AI models predict the next most likely word based on patterns in data.
They do not have real-world awareness or a true concept of “truth.”

That is something to keep in mind when dealing with AI.

Google Gemini AI explaining AI hallucinations.
Google Gemini AI on AI hallucinations.

Why We Should Double-Check the AI Output: A Bug Which Wasn’t

This is a concrete real-world example showing how AI-generated results should not be 100% completely trusted.

Recently I asked Claude to review the code of my WinReg C++ library (which is a C++ high-level wrapper around the low-level C-interface Windows Registry API).

As a result of its analysis, Claude reported that there were zero-length bugs in my code, in particular Claude stated that zero-length REG_SZ/REG_EXPAND_SZ values crash the GetStringValue, GetExpandStringValue, TryGetStringValue and TryGetExpandStringValue methods of the RegKey class.

In particular, Claude noted that I correctly guarded against dataSize == 0 in the binary-returning getters (like RegKey::GetBinaryValue), but the string getters do not have such guard; they unconditionally do:

result.resize((dataSize / sizeof(wchar_t)) - 1);

Claude specified that REG_SZ and REG_EXPAND_SZ values can be legitimately stored with cbData == 0 (zero bytes, no NUL at all; different from an empty string made by a single NUL ‘\0’).

If you substitute zero for the dataSize variable in the above statement, you end up with:

result.resize(SIZE_MAX);

which would throw a std::length_error exception.

An alleged bug reported by Claude AI on a zero-length edge case in my WinReg C++ library.

Claude proposed to fix the above code using the same edge-case check logic I had already implemented in the binary getters to guard against the zero-length case:

if (dataSize == 0)
{
    result.clear();
}
else
{
    result.resize((dataSize / sizeof(wchar_t)) - 1);
}

My WinReg library is quite battle-tested, and there were bugs related to some edge cases that I had already fixed, so I was curious, and tried writing a zero-length string value in the registry, and read it back with my existing code. And I noted that (at least in Windows 11 where I tested my code) the dataSize == 0 condition was not hit at run-time.

That is because in my C++ code I invoke the RegGetValue(W) API, which by contract guarantees to return a NUL-terminated string, even if the string stored in the registry doesn’t have a NUL-terminator. (This is not the case for older APIs like RegQueryValueEx.)

I replied to Claude pointing that out, and Claude corrected itself:

Correcting Claude.
Claude self-correction after I pointed out its bug analysis was probably wrong.

You’re right, and thanks for the pushback — I should have accounted for RegGetValueW‘s null-termination guarantee before flagging that as a bug.

Those AI tools can be very powerful, but the key takeway here is that we should not forget that they are just tools, and we should not trust AI-generated output and code 100%, because bugs and wrong assumptions can be hidden in that AI code, too.