Neue MSDN Foren nun auch in Deutsch

In der englisch sprechenden Welt haben die MSDN Foren den NNTP Foren weitgehend den Rang abgelaufen.
Mit dem Launch von VS-2005 gab es auch den Versuch diese in Deutsch zu starten, was aber wirklich in die Hose ging, mangels Werbung, Angebot, Verweis und Akzeptanz der Pros und Regulars. Es wurden hier gerade einmal Untergruppen für die Visual-Express Versionen geschaffen. Dieses alte Forum ist noch zu finden unter:
http://forums.microsoft.com/msdn-de/default.aspx?siteid=9
Nicht mal 1000 Threads 6 Bereichen in mehr als 3 Jahren sind ein ziemlich müdes Ergebnis.

Nun wird ein zweiter Versuch gemacht mit einem weitaus größeren Angebot unter
http://social.msdn.microsoft.com/Forums/de-DE/categories/
Der Inhalt der alten Foren wurde auch in die neuen Foren Bereiche migriert.

Der Vorteil gegenüber dem alten System ist offensichtlich:

  • Im alten System waren die Threads und Foren nach Sprache getrennt. Im neuen System erscheinen alle Threads über alle MSDN Foren aller Sprachen in einer Liste.
  • Die UI hat sich entschieden verbessert.
  • Ein Bewertungsbereich und Scoring Bereich für die Mitglieder wurde erweitert.
  • … und scheinbar wird auch versucht etwas mehr Werbung zu machen.

Nun bleibt abzuwarten ob diese Foren wirklich genutzt werden für C++ und Visual Studio allgemein. Oder ob die C++ Regulars lieber doch auf NNTP mit nntp://microsoft.public.de.vc verbleiben oder das bekannte Forum auf http://www.c-plusplus.de/forum nutzen. Über die Niveauunterschiede zwischen diesen beiden Foren brauche ich nichts zu sagen 😉 …

Anmerkung:
Ein Anachronismus ist sicherlich, dass man über die Community Links in der lokalen MSDN Installation oder auch über die Menüpunkte im Visual Studio (MSDN-Foren) sowohl bei der 2005er wie auch der 2008er Version, immer noch nur das alte Englische MSDN Forum erreicht, dass auch schon längst abgelöst wurde, und das man aktuell keine Möglichkeit hat aus VS, die deutschen Communities zu erreichen.
Ich frage mich manchmal warum die Community Aktivitäten von Microsoft, gerade im nicht Englisch sprechenden Bereich, selten einmal koordiniert erscheinen. Es kommt mir so vor, als ob die Betreuung dieser Bereiche einfach jemanden aufgedrückt wird, der genug Anderes zu tun hat und diese Bereiche eher nebenbei betreuen „muss“… und auf Befehl von irgendwo oben wird dann eben mal mit Hauruck „Irgendwas“ gemacht, weil man muss ja mal was machen…

Selbst reingelegt beim Test von „XP oder später“

Manche Codezeilen schreibt man ja einfach im Schlaf so in etwa wie diesen hier

static const OSVERSIONINFO &GetOSVersionInfo()
{
 static OSVERSIONINFO osVersionInfo;
 if (osVersionInfo.dwOSVersionInfoSize==0)
 {
  osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
  ::GetVersionEx(&osVersionInfo);
 }
 // return pointer to struct
 return osVersionInfo;
}

bool OSIsWinXP()
{
 // Check if OS is XP or later
 const OSVERSIONINFO &osvi= GetOSVersionInfo();
 return (osvi.dwPlatformId & VER_PLATFORM_WIN32_NT)!=0 &&
     osvi.dwMajorVersion>=5 &&
     osvi.dwMinorVersion>=1;
}

Der Sinn und Zweck ist eindeutig. Ich benötige diese Funktion um zu Testen ob Windows XP oder ein späteres OS wie Vista oder Windows 7 installiert ist. Dumm nur das dieser Code dämlich falsch ist.
Die Betriebssysteme haben die folgenden internen Versionsnummern
5.0 – Windows 2000
5.1 – Windows XP
5.2 – Windows Server 2003
6.0 – Windows Vista
6.1 – Windows 7 (Anmerkung: idotisch, dass hier nicht 7.0 verwendet wird)

Als ich den Code schrieb war Windows XP gerade draußen und selbst Windows Server 2003 gerade am Horizont. Dämlicherweise schrieb ich in dem Test osvi.dwMajorVersion>=5 && osvi.dwMinorVersion>=1.
ohne natürlich daran zu denken, dass ein späteres OS wieder mit einer 0 als minor Version kommen könnte.
Dadurch ergibt sich natürlich das der Test für alle Betriebssysteme nach Windows XP funktioniert nur nicht für Windows Vista  weil eben die Minor Version hier 0 ist. Ich war drauf und dran mal wieder einen Bug einzureichen bis mir schlagartig klar war, dass nicht Vista einen Fehler hat sondern mein eigener Code.

Der korrekte Test muss natürlich so lauten:

bool OSIsWinXP()
{
 // Check if OS is XP or later
 const OSVERSIONINFO &osvi= GetOSVersionInfo();
 return (osvi.dwPlatformId & VER_PLATFORM_WIN32_NT)!=0 &&
   (osvi.dwMajorVersion>5 ||    // May be vista or later
       (osvi.dwMajorVersion==5 &&    // that's XP
        osvi.dwMinorVersion>=1));
}

Code wie im Schlaf zu schreiben bringt es manchmal eben nicht. 😉

Tooltips und Customdraw

Customdraw ist für mich erste Wahl, wenn es um das Anpassen von Ausgaben in Controls geht, zudem ein subclassing von WM_PAINT mit Erhalt der Grundfunktionen eigentlich nicht möglich ist (ich werde dazu demnächst noch mal schreiben).

Liest man die Anleitung zu NM_CUSTOMDRAW und Tooltips, bekommt man den Eindruck, dass man wie bei einem List Control an jeder Stelle eingreifen kann. Vor dem Zeichnen, nach Löschen des Hintergrundes und so weiter: CDRF_NOTIFYITEMDRAW, CDRF_NOTIFYPOSTERASE, CDRF_NOTIFYPOSTPAINT, CDRF_NOTIFYSUBITEMDRAW werden in der Doku erwähnt.

Diese Informationen sind komplett irreführend, denn nur CDRF_NOTIFYPOSTPAINT wird vom Tooltip akzeptiert und beachtet. Man kann z.B. nicht auf die Ausgabe des Textes alleine übernehmen und nur das Löschen des Hintergrundes dem Control überlassen. Es wird wirklich nur CDRF_NOTIFYPOSTPAINT berücksichtigt ( ich habe mich durch den Assembler-Code der COMCTL32.DLL durch gedebuggt).
Auch die Rückgabe von CDRF_NEWFONT kann man sich sparen. Man muss nur einen neuen Font selektieren und er wird berücksichtigt.

Was in der Dokumentation auch zu kurz kommt, ist, dass NM_CUSTOMDRAW mit CDDS_PREPAINT zweimal kurz hintereinander aufgerufen wird. Beim ersten Mal ist DT_CALCRECT in NMTTCUSTOMDRAW::uDrawFlags gesetzt ist und beim zweiten mal nicht mehr. Man hat dadurch die Möglichkeit die Größe des Controls mit NMCUSTOMDRAW::rc zu kontrollieren. Gut beschrieben ist das nicht in der MSDN sondern in einem alten Artikel des MSJ aus dem Otkober 1996, wer weiß wann der verschwinden wird.

Die Implementierung hier ist einfach halbherzig, leider. Die Möglichkeiten wären so genial, hier ein bisschen Fettgedrucktes, dort noch mal ein Icon… Schade…

VS Tipps & Tricks: Der unbekannte CString Konstruktor…

CString nimmt natürlich auch in einem seiner Konstruktoren einen LPCTSTR . Dieser Konstruktor hat aber noch eine versteckt eingebaute Funktion. Man kann CString auch mit MAKEINTRESOURCE(id) verwendet. Aus der Dokumentation geht dies nicht eindeutig hervor, aber zumindest findet man es am Rande erwähnt.
Ist also das High-WORD des LPCTSTR gleich NULL dann wird das LOWORD verwendet um die entsprechende String-Ressource zu laden.
Ist die Ressource nicht vorhanden wird in der Debugausgabe ein entsprechender Trace erzeugt.

Benötigt man also temporär eine String Variable so kann man direkt in einem Statement die entsprechende String-Resource laden:

CString strMyText(MAKEINTRESOURCE(IDS_MY_STRING));
strMyText += strSomeOther;
strMyText += CString(MAKEINTRESOURCE(IDS_MY_TEXT_TO_APPEND));

WM_FLOATSTATUS der nette Helfer für eigene Popup Fenster

Manchmal entwirft man eigene Popup Fenster entwirft, die auch kurzfristig den Fokus bekommen sollen, wie z.B. ein Dropdown Fenster ähnlich einer Combobox. In diesem Fall hat man das Problem, dass das Main Fenster (Parent) als nicht mehr aktiv angezeigt wird, d.h. die Rahmenfarbe ändert sich, obwohl das eigentlich hier unerwünscht ist.

Eine Lösung wäre es WM_NCACTIVATE neu an das Parent zu versenden wenn WM_ACTIVATE eintrifft.
Die MFC hat aber hierfür eine weitaus bessere Technik, die sofort vermeidet, dass das Parent inaktiv angezeigt wird ❗
Man muss dazu nur die interne MFC Fensternachricht WM_FLOATSTATUS behandeln, die auch in der TN024 beschrieben, ist behandeln.

Etwas in dieser Art

...
   ON_MESSAGE(WM_FLOATSTATUS,OnFloatStatus)
...

LRESULT CMyDropDownWnd::OnFloatStatus(WPARAM wParam, LPARAM)
{
    return (wParam & FS_SYNCACTIVE) ? TRUE : FALSE;
}

und man verhindert dadurch, das das Parent inaktiv wird, weil man signalisiert, dass das neue Popup-Fenster synchron aktiv ist (FS_SYNCACTIVE). Die gleiche Technik wird auch innerhalb der Toolbars verwendet, die auch alle zusammen mit dem Parentframe alle aktiv oder alle inaktiv erscheinen.

Mein Blog ist 2 Jahre alt geworden + Gesegnete Weihnachtszeit + Ein gutes neues Jahr

Im Mitte Dezember 2006 hatte ich mir endlich die Zeit genommen diesen Blog einzurichten. Ich habe mit einigen Providern experimentiert bin aber dann schnell zu einer eigenen WordPress Installation gekommen, die ich ja auch immer noch erfolgreich verwende.

Schnell sind diese 2 Jahre sind vergangen und insgesamt 267 Beiträge wurden geschrieben. Und immer noch steigen die Zugriffszahlen langsam, aber stetig an, wenn ich der WordPress Blog-Statistik glauben darf. Ich hatte nicht gedacht, so viele Leser zu erreichen. Aber diese Bestätigung ist auch gut, denn was nützt ein Blog ohne Leser 😉

Allen regelmäßigen Kommentatoren sei hier auch einmal Dank für die immer guten und konstruktiven Beiträge.

Ich wünsche allen eine gesegnete Weihnachtszeit und ein gutes neues Jahr!

PS: In meinem Sidebar habe ich jetzt auch eine zusätzliche Combobox eingebaut, die es erlaubt weiter zurück in die Vergangenheit zu gehen als nur die bisherigen 18 Monate.

Der etwas bessere CMemDC

CMemDC aus dem Artikel Flicker free drawing with MFC ist wohl der Klassiker für Doublebuffering und ist wohl jedem MFC Entwickler bekannt.

Er macht was er soll und ich habe ihn selbst über Jahre hinweg unverändert verwendet. Solange man einfache Sachen macht und ausschließlich den MM_TEXT Mappingmode verwendet ist alles OK.
Hat man sich aber was spezielles – zoomfähiges – zusammengebaut mit MM_ANISOTROPIC dann funktioniert das Ganze nicht mehr, weil Keith an den Window Origin Koordinaten dreht und nicht am Viewport.

Meine abgewandelte Variante trägt einer entsprechende Verwendung auch für andere Mappingmodes Rechnung. Es müsste IMHO für jeden funktionieren. Intensiv getestet habe ich es mit MM_ANISOTROPIC.

Will/muss man auch an den Viewport Koordinaten drehen, dann sollten die alten Viewport Koordinaten gelesen werden und dann entsprechend durch ein Offset geändert werden.
Alles anderen Werte wie die Extents können beliebig verändert werden.
Bei der Verwendung sollte MM_TEXT eingeschaltet sein (entsprechende ASSERTs habe ich ergänzt). MM_TEXT ist normalerweise gesetzt, wenn CMemDC direkt nach Instanzierung des CPaintDC zum Einsatz kommt. Der Destruktor setzt dann den Mappingmode auf MM_TEXT zurück.

Dieser neue, modifizierte CMemDC kann einfach die bisherige Implementierung ersetzen.

Have fun & Happy coding 🙂

class CMemDC : public CDC
{
public:
  // constructor sets up the memory DC
  CMemDC(CDC* pDC)
    : CDC()
    , m_pDC(pDC)
    , m_pOldBitmap(NULL)
    , m_bMemDC(!m_pDC->IsPrinting())
  {
    ASSERT(pDC != NULL);

    if (m_bMemDC)
    {
      // Create a Memory DC.
      // At this moment we should have mapping mode text
      ASSERT(m_pDC->GetMapMode()==MM_TEXT);
      ASSERT(m_pDC->GetWindowOrg()==CPoint(0,0));
      ASSERT(m_pDC->GetViewportOrg()==CPoint(0,0));

      // Get the clip box and create bitmap for this size
      m_pDC->GetClipBox(&m_rect);
      CreateCompatibleDC(m_pDC);
      m_bitmap.CreateCompatibleBitmap(m_pDC, 
              m_rect.Width(), m_rect.Height());
      m_pOldBitmap = SelectObject(&m_bitmap);

      // Adjust the view port so that we hit the clip rect.
      SetViewportOrg(-m_rect.left, -m_rect.top);
      IntersectClipRect(m_rect);

      // Fill background in case the user has overridden
      // WM_ERASEBKGND.  We end up with garbage otherwise.
      FillSolidRect(m_rect, m_pDC->GetBkColor());
    }
    else
    {
      // Make a copy of the relevant parts of the current DC for printing
      m_bPrinting = m_pDC->m_bPrinting;
      m_hDC     = m_pDC->m_hDC;
      m_hAttribDC = m_pDC->m_hAttribDC;
    }
  }

  // Destructor copies the contents of the mem DC to the original DC
  ~CMemDC()
  {
    if (m_bMemDC)
    {
      // The mapping mode might effect the BitBlt. So we need to return to
      // MM_TEXT. This makes m_rect.left and m_rect.top again the
      // coordinates of our clipped rectangle. And to make sure that the
      // coordinates are really used we just clear the ViewportOrg and the
      // WindowOrg
      SetMapMode(MM_TEXT);
      SetViewportOrg(0,0);
      SetWindowOrg(0,0);

      // Copy the off screen bitmap onto the screen.
      // For this we just make sure that we really target the rectangle of
      // our temporal bitmap.
      m_pDC->BitBlt(m_rect.left, m_rect.top, 
              m_rect.Width(), m_rect.Height(),
              this, 0, 0, SRCCOPY);

      //Swap back the original bitmap.
      SelectObject(m_pOldBitmap);
    }
    else
    {
      // All we need to do is replace the DC with an illegal value,
      // this keeps us from accidentally deleting the handles associated
      // with the CDC that was passed to the constructor.
      m_hDC = m_hAttribDC = NULL;
    }
  }

  // Allow usage as a pointer
  CMemDC* operator->()  {   return this;  }

  // Allow usage as a pointer
  operator CMemDC*()  {   return this;  }

private:
  CBitmap  m_bitmap;    // Offscreen bitmap
  CBitmap* m_pOldBitmap;  // bitmap originally found in CMemDC
  CDC*   m_pDC;     // Saves CDC passed in constructor
  CRect  m_rect;    // Rectangle of drawing area.
  bool   m_bMemDC;    // true if CDC really is a Memory DC.
};

Aus zwei mach eins: Wie man zwei Cursor kombinieren kann

Wer komplexere UIs baut, der kommt um Drag&Drop oder andere Extrafunktionen mit der Maus nicht herum. Um den Benutzer gut zu unterstützen verwendet man natürlich auch spezielle Cursor.
Auffällig ist aber oft genug der Unterschied zwischen den schönen Standardzeigern im 3D-Stil und den oft flachen Zeigern, die gerade mal zusätzlich ein Plus oder ein Stoppzeichen tragen. Oder ganz und gar der Unterschied , wenn man eigene Cursorstile verwendet, wie z.B. Dirigent oder Hände.

Ich habe mich bei meinem aktuellen Projekt gefragt, warum man eigentlich nicht den aktuellen Standard-Cursor verwendet und diesen zusätzlich mit dem entsprechenden Symbol versieht (Pluszeichen, Stopp, Dragframe etc). Das würde besser aussehen und Arbeit sparen, weil man sich nur noch Gedanken um die Extrasymbolik machen muss und der Benutzer behält seinen eingestellten normalen Cursor.

Schaut man sich den Explorer unter XP+Vista an, dann macht man die Entdeckung, dass der es genauso macht. Der aktuelle Cursor wird beim Drag&Drop Vorgang um ein Stopp- oder Pluszeichen ergänzt.

Warum es also nicht selber auch so machen ❓

Meine Suche im Internet zu diesem Thema: „Wie kombiniert man zwei Cursor zu einem?“, war nicht von Erfolg gekrönt. Beispielcode dazu habe ich nicht gefunden. Aber auch wirklich gar nichts.
Also selbst Hand anlegen.

Bei meinem ersten Versuch wollte ich die Cursor-Bitmaps direkt manipulieren. Bei meiner Untersuchung und dem ersten Democode wurde klar, dass Windows gar keinen Unterschied mehr zwischen Icons und Cursor macht. Erstaunlich ❗ Ob Icon oder Cursor spielt eigentlich keine Rolle. HCURSOR und HICON sind identische Typedefs. Also egal ob toller Farbcursor oder monochromer Cursor, alles gleich.
Mit dieser Entdeckung nahm ich schnell Abstand von BitBlt und Konsorten und verwendete eine Imagelist, die genau diese Funktion des Overlays von Symbolen bereits unterstützt und zudem auch noch perfekt mit Icons umgehen kann.

Herausgekommen ist der folgende Code, der es erlaubt zwei Icons, oder Cursor zu überlagern und ein neues Icon oder einen neuen Cursor zu erzeugen.

Man muss sich aso nur mit LoadCursor, den aktuellen Cursor laden und kann diesen damit ganz einfach modifzieren. Nicht vergessen: Das erzeugte Icon/Cursor muss allerdings mit DestroyIcon auch wieder entsorgt werden. Das Ganze habe ich der Einfachheit halber mit MFC Funktionen geschrieben, aber das Ganze in pure WinAPI zu transformieren dürfte nicht schwer sein. 😉

 Hier nun der Code. Have fun!

HICON CombineIcons(HICON hIcon1, HICON hIcon2)
{
 // Remember that HCURSOR and HICON are identical!
 // hIcon1 is overlayed by hIcon2.
 // hIcon2 isn't adjusted in size or position.
 // It just overlays hIcon1
 // Get bitmaps of icon 1
 ICONINFO iconInfo;
 ::ZeroMemory(&iconInfo,sizeof(iconInfo));
 if (!GetIconInfo(hIcon1,&iconInfo))
  return NULL;

 // Attach the bitmaps to get them automatically freed
 // upon error.
 CBitmap bitmap, mask;
 bitmap.Attach(iconInfo.hbmColor);
 mask.Attach(iconInfo.hbmMask);

 // Get size and width
 BITMAP bm;
 if (bitmap.m_hObject)
  bitmap.GetObject(sizeof(bm),&bm);
 else
  mask.GetObject(sizeof(bm),&bm);

 // Get the color depth from the icon and create an image list
 // Remember we need a
 UINT flags = 0;
 switch (bm.bmBitsPixel)
 {
 case 4:  flags = ILC_COLOR4;  break;
 case 8:  flags = ILC_COLOR8;  break;
 case 16: flags = ILC_COLOR16; break;
 case 24: flags = ILC_COLOR24; break;
 case 32: flags = ILC_COLOR32; break;
 default: flags = ILC_COLOR4;  break;  
 }
 CImageList il;
 // be ware that the monochrom cursor bitmap is twice the height
 if (!il.Create(bm.bmWidth,
      bm.bmHeight/(iconInfo.hbmColor!=NULL ? 1 : 2),
      ILC_MASK|flags,2,2))
  return NULL;

 // Load the both icons into the image list
 il.Add(hIcon1);
 il.Add(hIcon2);

 // Define the second icon as an overlay image
 il.SetOverlayImage(1,1);

 // Get a new icon with icon 2 overlayed
 HICON hCombined = ImageList_GetIcon(il.m_hImageList,0,
              ILD_NORMAL|INDEXTOOVERLAYMASK(1));
 if (!hCombined)
  return NULL;

 // Need the icon infos for this new icon
 ICONINFO iconInfoCombined;
 ::ZeroMemory(&iconInfoCombined,sizeof(iconInfo));
 if (!GetIconInfo(hCombined,&iconInfoCombined))
  return NULL;

 // Destroy the combined icon, we just have the bitmap and the mask
 ::DestroyIcon(hCombined);

 // Get the bitmaps into objects to get them automatically freed
 CBitmap bitmapCombined, maskCombined;
 bitmapCombined.Attach(iconInfo.hbmColor);
 maskCombined.Attach(iconInfo.hbmMask);

 // Get the hotspotinto and cursor data from
 // the ICONINFO of hCursor1
 iconInfoCombined.fIcon = iconInfo.fIcon;
 iconInfoCombined.xHotspot = iconInfo.xHotspot;
 iconInfoCombined.yHotspot = iconInfo.yHotspot;

 // OK we have can create a new Cursor out of the target
 // Don't forget to use DestroyIcon for the new Cursor/Icon
 return ::CreateIconIndirect(&iconInfoCombined);
}

MSVSMON: Visual Studio Remote Debugging Monitor will not be able to debug applications because…

Da schreibe ich einen netten Artikel über Remote Debugging und schon geht es doch nicht so einfach wie ich schreibe.

Manch ein Entwickler wird von der folgenden Nachricht begrüßt, wenn er MSVSMON.EXE startet:

Visual Studio Remote Debugging Monitor will not be able to debug applications because the ‚Network access: Sharing and security model for local accounts‘ local security policy option is set to ‚Guest only – local users authenticate as Guest‘. This can be configured with the ‚Local Security Settings‘ administration tool.
Do you want to continue?    (Use /noguestonlywarn to suppress this warning)

Nun auch keine Tragik. Dann kommen wir aber um einen Neustart nach Änderungen der Lokalen Richtlinien nicht herum. Aber man muss erst mal wissen was mit dieser Meldung gemeint ist, wenn man ein deutsches OS benutzt:

  1. Systemsteuerung starten.
  2. Leistung und Wartung -> Verwaltung -> Lokale Sicherheitsrichtlinie
  3. In den Lokalen Sichereinstellungen auf
    Lokale Richlinien -> Sicherheitsoptionen
  4. Dort dann Netzwerkzugriff: Modell für gemeinsame Nutzung und Sicherheitsmodell für lokale Knoten auswählen.
  5. Umstellen auf: Klassisch – lokale Benutzer authentifizieren sich als sie selbst
  6. Reboot

HTH
Siehe auch:
How to: Set Up Remote Debugging
How to debug on computers that are running Windows XP and that are in the same Workgroup in Visual Studio .NET or in Visual Studio 2005

VS Tipps & Tricks: Heap Bugs finden (Teil 4)

In meine ersten Artikeln über Heap-Bugs habe ich bereits erwähnt, dass die CRT aber auch Windows selbst Speicher unter bestimmten Umständen vorbelegt bzw. beim Freigeben des Speichers mit einem festen Wert löscht.

Für einen Entwickler ist es gut zu wissen welche Werte durch wen gesetzt werden. Zudem erleichtert einem dieses Wissen auch das Debuggen und die Identifikation von Problemen im Zusammenhang mit dem Heap, deshalb habe ich hier mal diese Magic-Bytes, die von Microsoft verwendet werden hier zusammengetragen.

Würde man im Debugger zum Beispiel eine Variable mit dem Wert 0xCCCCCCCC entdecken, dann ist davon auszugehen, dass man diese Variable auf dem Stack nicht initialisiert hat.

  • 0xABABABAB
    Wird von HeapAlloc als Wert für die Guard Bytes („no man’s land“) vor und hinter Speicherblöcken verwendet.
  • 0xBAADF00D
    Wird von LocalAlloc(LMEM_FIXED) verwendet um nicht nicht initialisierten Speicher im Heap zu kennzeichnen.
  • 0xCCCCCCCC
    Wird von der Debug-CRT verwendet um nicht initialisierten Stack zu kennzeichnen.
  • 0xCDCDCDCD
    Wird von der Debug-CRT verwendet um nicht initialisierten Speicher im Heap zu kennzeichnen.
  • 0xDDDDDDDD
    Wird von der Debug-CRT verwendet um freigegebenen Speicher im Heap zu kennzeichnen.
  • 0xFDFDFDFD
    Wird von vom Debug-Heap verwendet für Guard Bytes („no man’s land“), vor und hinter Speicherblöcken.
  • 0xFEEEFEEE
    Wird von HeapFree() verwendet um freigegebenen Speicher zu kennzeichnen.

Siehe auch: http://en.wikipedia.org/wiki/Magic_number_(programming)