Saturday, August 16, 2025

Careful with AI tooling

AI tooling

 Since some period I started working with AI tooling. Mostly Gemini and Co pilot inside Visual Studio. The experience is a bit of mixed feelings about this. Sometimes it has good code completion suggestions. Co pilot's function name suggestion are also very welcome.

 On the other hand the AI is still full of mistakes. Lately I asked Gemini for camera sharpness algorithm. It came up with a good algorithm but the actual OpenCV function calls and parameters were incorrect. I once asked Gemini to get the real sample time from an 'IMediaSample'. It suggest to use the non existing 'GetSampleTime'. There is already a 'GetMediaTime' function but this returns the stream time; i.e. the time since the graph was running and not the time from the start of the video.

 Even worse that sometimes AI tooling can suggest plain bugs. I was implementing a swap of width and height and Co pilot's code complete came up with the following code snippet:

// NOTE: incorrect 
Size sz = ...;
if (sz.GetWidth() < sz.GetHeight())
{
   sz.SetWidth(sz.GetHeight());
   sz.SetHeight(sz.GetWidth());
}

This of course doesn't swap but sets the width and height on the old height value.

 AI tooling can be helpful but are still not on the level to be trusted blindly. They also now help with limited scope; e.g. code blocks; algorithms and functions. I am not aware if they can help in refactoring and extending architecture spanning solutions.

 

Debugging GDI drawing

GDI debugging

 The other day I had to debug a hard to track drawing bug. The application is built with the MFC framework so it still uses GDI on places to draw custom controls.

 The incorrect drawing artifact was displayed after an invocation of 'DrawText'. This was unexpected since the function only measured the size. It had the flag 'DT_CALCRECT' which does not draw to the screen. Eventually I realized that  GDI batches calls so probably the buggy overdrawing had already taken place before. What was needed:

  •  suppress GDI's caching mechanism through 'GdiSetBatchLimit'.
  •  use direct drawing; so no memory device context

 With this in place indeed it could be seen that the mistake happened earlier in the code and that the 'DrawText' invocation was merely a flush of the GDI batch.

 Be aware that suppressing  GDI's batch might not always work. When the window where the drawing took place was on the primary monitor the batch mode could be turned off but on the second monitor it still cached its calls.

Sunday, July 27, 2025

Watch out for an old VC++ runtime

 VC_redist.x64.exe

 For C/ C++ applications the VC++ runtime needs to be installed on the computer. The other day we experienced crashes when a component developed with a late version of VS2022 was crashing on a fresh installation of Windows 11. It turned out that this Windows 11 still uses an old version of the VC++ runtime which could crash the application (most notably in grabbing a std::mutex lock). After updating the PC with a recent version of 'VC_redist.x64.exe' the problem was solved.

 

Wednesday, July 23, 2025

ark.intel.com

 

ark.intel.com

 Intel had a wonderful website where one could easily lookup the processor and see what capabilities (e.g. SSE 4.2; AVX; AVX2) it had. In a recent visit it was completely overhauled and they have removed (or hidden) the easy possibility to lookup your processor with one click. Thanks Intel for modernizing their website and destroying a valuable functionality.


Sunday, June 29, 2025

Watch out for atan change in Visual Studio 2022 17.14.6

atan

 Recently we updated Visual Studio 2022 17.14.6 and the regression test reported errors. It turned out that atan implementation was changed resulting a different value for debug vs release builts with CPU's having AVX2. One can recreate this with the following values:

    const double ax          = 38.176459921094995;
    const double ay          = 15.964755390006060;
    const double dblRotation =  atan(ay/ax);

 We had to relax the equality checks; even for deterministic calculations.


Sunday, June 1, 2025

Careful with std::wfstream

wchar_t file streams

 The std::wfstream is similar to std::fstream except it accepts wchar_t. However it does not write std::wchar_t characters to file. Suppose the following code:

   std::wofstream ofs;
   ofs.open(L"c:\\temp\\1.txt" , std::ios_base::out | std::ios_base::binary) ;
   ofs.write(L"ABC", 3);

 On the Windows platform this writes just single bytes characters to the file. The reason is that the locale bound to the file stream translates wchar_t to char. This can be fixed by using a custom locale which doesn't do this. This translation is quite unexpected behavior since the function prototypes are defined in terms of wchar_t. It is also different compared to the wchar_t string streams: std::wstringstream does write wchar_t strings unaffected.

 This page was inspired by a YouTube comment of me where I stated that the C FILE api is less surprising. Of course there is always a clown who thinks better but probably doesn't know anything about above issue. With C stream I/O FILE and 'fwrite' the bytes are transferred to the file without interpretation and alteration.

FILE wrapper

 Jason Turner goes a lengthy way of wrapping the C FILE api but using a wrapper class would probably be simpler:

class c_file
{
public:
   c_file()
      : m_fp(nullptr)
   {
   }
   
   explicit c_file(const std::filesystem::path& rpth, const char* pszMode)
      : m_fp(fopen(rpth.string().c_str(), pszMode))
   {
   }

   ~c_file()
   {
      if (m_fp)
      {
         fclose(m_fp);
      }
   }

   c_file(const c_file&) = delete;

   c_file(c_file&& rOther) noexcept
      : m_fp(std::exchange(rOther.m_fp, nullptr))
   {
   }

   c_file& operator=(const c_file&) = delete;

   c_file& operator=(c_file&& rOther) noexcept
   {
      std::swap(m_fp, rOther.m_fp);
   }

   explicit operator bool() const
   {
      return m_fp;
   }

   size_t read(void* pBuffer, size_t size, size_t count)
   {
      return fread(pBuffer, size, count, m_fp);
   }

   size_t write(const void* pBuffer, size_t size, size_t count)
   {
      return fwrite(pBuffer, size, count, m_fp);
   }

   // etc.

private:
   FILE*    m_fp;
};

Links

Sunday, July 21, 2024

C++ horrible aspects

C++ horrible aspects

 Linus Torvalds described C++ as being a horrible language. While C++ has its dark corners I choose it any day over any other language. Especially compared to C with its major security liabilities. There are some questionable aspects though: 

  • 'rvalue' references becoming 'lvalue' references. Not sure who invented this but he or she should be banned from the committee. Super confusing that a type can change.
  • universal references and perfect forwarding. Again a very confusing idea to reuse the 'rvalue' reference syntax. The reference collapsing rules doesn't make it easier either
  • two phase lookup. Confusing rule which could have been solved by stating that a template definition is only checked at instantiation time. No more need for 'typename' or making types and member functions (non) dependent since at instantiation time all type and context information is known
  • lack of uniformity in STL. For example there is reset and clear. Some algorithm's have _if variants when taking functors; others not.
  • functional programming style over object oriented. Why not make the regex functions member functions? It prevents clutter of std namespace. It will probably also help Intellisense to build up its database which is important help in IDE's these days. 
  • uniform initialization. Again the committee made a mistake. The issue could be fixed by requiring double braces in case constructor invocation (e.g.std::vector<size_t>{{2}})
  • the ranges library has some strange aspects as well as can be seen here

Besides these aspects C++ misses out on an extended standard library. Especially compared to .NET or Java where many things are present in their extensive standard library. One need frequent 3th party libraries (e.g. Boost) for basic things. This could have been alleviated if there was a standard package manger like in Python with de facto libraries but again there isn't.


Watch out for hypes in ICT

Hypes  ICT has a rich history of hypes where people thought that this would be a panacea for all problems. These hypes lasted for some time ...