Forum: PC-Programmierung Windows: Buffer too small


von LFX3 (Gast)


Lesenswert?

Guten Tag,

ich habe aus dem Buch "C - Einführung und professionelle Anwendung" 
folgendes Beispiel in Visual C++ 2008 Express eingegeben:
1
#include <stdio.h>
2
#include <windows.h>
3
4
HINSTANCE hInst = 0;
5
char szAppName[] = "Basis";
6
char szTitle[100] = "Willys Titelleiste";
7
8
BOOL InitApplication ();
9
BOOL InitInstance (int);
10
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
11
12
void onPaint (HWND);
13
14
int WINAPI WinMain (  HINSTANCE hInstance,
15
            HINSTANCE hPrevInstance,
16
            LPSTR    lpCmdLine,
17
            int       nCmdShow)
18
{
19
20
  MSG msg;
21
  hInst = hInstance;
22
23
  if (!InitApplication () ) return FALSE;
24
  if (!InitInstance (nCmdShow) ) return FALSE;
25
26
  while (GetMessage (&msg, NULL, 0, 0))
27
  {
28
    TranslateMessage (&msg);
29
    DispatchMessage (&msg);
30
  }
31
32
33
34
  return (msg.wParam);
35
}
36
37
BOOL InitApplication ()
38
{
39
  WNDCLASSEX wc;
40
41
  wc.cbSize = sizeof(WNDCLASSEX);
42
  wc.style = CS_HREDRAW | CS_VREDRAW;
43
  wc.lpfnWndProc = (WNDPROC)WndProc;
44
  wc.cbClsExtra = 0;
45
  wc.cbWndExtra = 0;
46
  wc.hInstance = hInst;
47
  wc.hIcon = LoadIcon ( NULL, IDI_QUESTION);
48
  wc.hCursor = LoadCursor ( NULL, IDC_WAIT);
49
  wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
50
  wc.lpszMenuName = NULL;
51
  wc.lpszClassName = szAppName;
52
  wc.hIconSm = LoadIcon (NULL, IDI_WINLOGO);
53
54
  return RegisterClassEx(&wc);
55
}
56
57
58
BOOL InitInstance (int nCmdShow)
59
{
60
  HWND hWnd;
61
  hWnd = CreateWindow(
62
      szAppName,
63
      szTitle,
64
      WS_OVERLAPPEDWINDOW,
65
      50,//CW_USEDEFAULT,
66
      100,
67
      500,
68
      250,
69
      NULL,
70
      NULL,
71
      hInst,
72
      NULL);
73
  if (!hWnd) return (FALSE);
74
  ShowWindow (hWnd, nCmdShow);
75
  UpdateWindow (hWnd);
76
77
  return (TRUE);
78
}
79
80
81
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
82
{
83
  
84
  switch (message)
85
  {
86
  case WM_PAINT:
87
    onPaint(hWnd);
88
    break;
89
  case WM_DESTROY:
90
    PostQuitMessage(0);
91
    break;
92
  default:
93
    return DefWindowProc (hWnd, message, wParam, lParam);
94
  }
95
96
  return 0;
97
}
98
99
100
101
void onPaint (HWND hWnd)
102
{
103
  PAINTSTRUCT ps;
104
  HDC hdc;
105
  TEXTMETRIC tm;
106
  char szZahl[10];
107
108
  int i = 0;
109
  int nXStart1, nXStart2, nYStart;
110
  int nAveCharWidth, nLineHeight;
111
112
  char* strMetrik[] = {  "Zeichenhoehe: ",
113
              "Hoehe oberhalb der Basislinie:",
114
              "Hoehe unterhalb der Basislinie:",
115
              "Hoehe des Bereichs fuer Umlaute:",
116
              "Abstand zwischen den Zeilen:",
117
              "Mittlere Zeichenbreite:",
118
              "Maximale Zeichenbreite:"
119
            };
120
121
  hdc = BeginPaint (hWnd, &ps);
122
123
  GetTextMetrics(hdc, &tm);
124
  nLineHeight = (int)(tm.tmHeight + tm.tmExternalLeading)+2;
125
  nAveCharWidth = (int)tm.tmAveCharWidth;
126
127
  nXStart1 = 5*nAveCharWidth;
128
  nXStart2 = nXStart1 + 40*nAveCharWidth;
129
130
  nYStart = 1*nLineHeight;
131
132
  for (i=0; i < 7; i++)
133
  {
134
    TextOut (hdc, nXStart1, nYStart, strMetrik[i], strlen(strMetrik[i]) );
135
136
    switch(i)
137
    {
138
    case 0: sprintf_s(szZahl, "%31d", tm.tmHeight);
139
        break;
140
    case 1: sprintf_s(szZahl, "%31d", tm.tmAscent);
141
        break;
142
    case 2: sprintf_s(szZahl, "%31d", tm.tmDescent);
143
        break;
144
    case 3: sprintf_s(szZahl, "%31d", tm.tmInternalLeading);
145
        break;
146
    case 4: sprintf_s(szZahl, "%31d", tm.tmExternalLeading);
147
        break;
148
    case 5: sprintf_s(szZahl, "%31d", tm.tmAveCharWidth);
149
        break;
150
    case 6: sprintf_s(szZahl, "%31d", tm.tmMaxCharWidth);
151
        break;
152
    };
153
154
    TextOut(hdc, nXStart2, nYStart, szZahl, strlen(szZahl) );
155
    nYStart += nLineHeight;
156
157
  }
158
159
  EndPaint (hWnd, &ps);
160
}


Ich erhalte folgende Fehlermeldung:

Debug Assertion Failed!
Program
...ges\textmetric\Debug\textmetric.exe
File f:\dd\vctools\crt_bld\self_x86\crt\src\vsprintf.c
Line 244
Expression:("Buffer too small", 0)



Kann mir jemand sagen, woran das liegt?


LFX3

von Karl H. (kbuchegg)


Lesenswert?

>  char szZahl[10];

>    case 0: sprintf_s(szZahl, "%31d", tm.tmHeight);


Wie soll denn eine Zahl, die du mit 31 Dezimalstellen als Text 
dargestellt haben willst (und der Text daher aus 31 Zeichen bestehen 
wird), in einen String passen, der gerade mal Platz für 9 Zeichen hat?

von Peter II (Gast)


Lesenswert?

irgendwie stimmen die parameter nicht mit der doku überein

sprintf_s(szZahl, "%31d", tm.tmHeight);

http://msdn.microsoft.com/de-de/library/ce3zzk1k%28v=vs.80%29.aspx

int sprintf_s(
   char *buffer,
   size_t sizeOfBuffer,
   const char *format [,
      argument] ...
);

von LFX3 (Gast)


Lesenswert?

Aua, danke für den Hinweis:


Statt
1
case 0: sprintf_s(szZahl, "%31d", tm.tmHeight);


muss es heißen:
1
case 0: sprintf_s(szZahl, "%3ld", tm.tmHeight);


VIELEN DANK
LFX3

von Karl H. (kbuchegg)


Lesenswert?

LFX3 schrieb:

>
1
> case 0: sprintf_s(szZahl, "%3ld", tm.tmHeight);
2
>

Es muss vor allen Dingen
1
sprintf_s( szZahl, sizeof(szZahl), "%3ld", tm.tmHeight);
heissen.
Auch wenn Microsoft mittels Template ...
1
template <size_t size>
2
int sprintf_s(
3
   char (&buffer)[size],
4
   const char *format [,
5
      argument] ... 
6
); // C++ only
... eine Automatik eingebaut hat, die dann greift, wenn der Compiler das 
Array selber sehen kann. Denn irgendwann hast du dann diesen Fall nicht 
mehr und dann ist das Kopfkratzen groß, was denn das Problem ist. Nichts 
gegen Komfort, aber zuviel Komfort macht nachlässig.

Und ob die "ld" richtig sind, muss man in der TEXTMETRIC Struktur 
nachsehen. Das steht
1
typedef struct tagTEXTMETRIC {  /* tm */
2
    int  tmHeight;
3
    int  tmAscent;
4
    int  tmDescent;
5
    int  tmInternalLeading;
6
    int  tmExternalLeading;
7
    int  tmAveCharWidth;
8
    int  tmMaxCharWidth;
9
    int  tmWeight;
10
    BYTE tmItalic;
11
    BYTE tmUnderlined;
12
    BYTE tmStruckOut;
13
    BYTE tmFirstChar;
14
    BYTE tmLastChar;
15
    BYTE tmDefaultChar;
16
    BYTE tmBreakChar;
17
    BYTE tmPitchAndFamily;
18
    BYTE tmCharSet;
19
    int  tmOverhang;
20
    int  tmDigitizedAspectX;
21
    int  tmDigitizedAspectY;
22
} TEXTMETRIC;

Nö. ld ist definitiv falsch. tmHeight ist vom Datentyp int. Also muss 
der Formatspecifier ein "d" sein und kein "ld".


Leg das Buch zur Seite und kauf dir erst mal ein vernünftiges 
Einsteigerbuch für C. Der Klassiker "Kernighan&Ritchie" wird immer 
wieder gerne genommen.
Wenn du den durch hast und auch verstehst, dann fallen dir die Fehler in 
diesem Buch dann auch auf. Alleine der Titel muss schon stutzig machen. 
Zwischen "Einführung" und "professioneller Anwendung" liegen im 
günstigen Fall so ca. 3 bis 4 Jahre und eine halbes Bücherregal an 
Literatur.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.