There must be something with char arrays that I am missing out on.
The procedure below had symptoms of memory overwrites. I have already rewrote it using allegro unicode routines. It works fine if compiled for release in MSVC, but I now notice it crashes when compiled in debug mode. The crash occurs right after this procedure has been run once. what is illegal here? how can I catch the overwrite or overread more specific? What statements do I have to make instead?
Thanks in advance.
| 1 | // shortens a string to a specified length. This is done by adding the \0 limiter. |
| 2 | void _setstrlen(char *string, int length) |
| 3 | { |
| 4 | if (ustrlen(string)>length) |
| 5 | *(string + length) = '\0'; |
| 6 | } |
| 7 | |
| 8 | #define strcpy2(dest, src) ustrzcpy(dest,sizeof(dest), src) |
| 9 | |
| 10 | // takes one long string and smartly cuts it into sentences given a width-limit. draws to scrbuf. |
| 11 | int draw_textblok(int limit, int issue) |
| 12 | { |
| 13 | char linebuf[801],text[801]; |
| 14 | int lines=0, |
| 15 | pos=0, // position in source text buffer |
| 16 | pos1=0, // position after lines already drawn |
| 17 | pos2, // |
| 18 | pos3, // |
| 19 | posmax; // size of source text buffer |
| 20 | |
| 21 | const int lineh=text_height((FONT *)fntdat[FNT04].dat)+2; |
| 22 | if (limit<200) limit=200; |
| 23 | |
| 24 | strcpy2(text,qst.briefing); |
| 25 | |
| 26 | posmax=ustrlen(text)-1; |
| 27 | |
| 28 | while (text[posmax]==' ') posmax--; // remove trailing spaces |
| 29 | |
| 30 | do |
| 31 | { |
| 32 | // find out when exceeding limit |
| 33 | do |
| 34 | { |
| 35 | usetat(linebuf, pos-pos1, ugetat(text, pos)); // linebuf[pos-pos1]=text[pos]; |
| 36 | _setstrlen(linebuf,pos-pos1+1); // linebuf[pos-pos1+1]=0; //endline |
| 37 | pos++; |
| 38 | } |
| 39 | while (text_length((FONT *)fntdat[FNT04].dat,linebuf)<=limit && pos<=(posmax+1)); |
| 40 | |
| 41 | // take back to first space, compensate last c++ |
| 42 | do pos--; while (ugetat(linebuf,pos-pos1)!=' ' && ugetat(linebuf,pos-pos1)!=0 && pos>pos1); |
| 43 | |
| 44 | // search for nearby of end of a sentence, or part of a sentence: |
| 45 | pos3=0; pos2=pos; |
| 46 | if (pos>20) do |
| 47 | { |
| 48 | if (ugetat(linebuf,pos2-pos1)==',' || ugetat(linebuf,pos2-pos1)=='.') pos3=pos2; |
| 49 | pos2--; |
| 50 | } |
| 51 | while (pos2>(pos-20) && pos3==0); |
| 52 | if (pos3>0) pos=pos3; |
| 53 | // put endline at place: |
| 54 | _setstrlen(linebuf,pos-pos1+1); |
| 55 | // remove heading spaces: |
| 56 | if (ugetc(linebuf)==' ') uremove(linebuf,0); |
| 57 | // then write the string |
| 58 | textprintf_centre_ex(scrbuf,(FONT *)fntdat[FNT02].dat,(limit/2)+1,lines*lineh,_col(ink),-1,linebuf); |
| 59 | |
| 60 | lines++; |
| 61 | pos1=pos+1; |
| 62 | } |
| 63 | while (pos<posmax && lines<8); |
| 64 | |
| 65 | return lines; |
| 66 | } |
A bit of advice: if you want to use the Allegro unicode routines properly, you cannot assume that a character is always one byte wide. If you want to assume that, there's no point using the Allegro unicode routines: all effort for no gain.
As for your problem, I suggest making use of the debugger to inspect the values of any data structures modified by the function and work your way backwards.
Off-topic: Isn't your Avatar from one of the Goblin games Gerwin?
thanks Peter,
more then one byte wide.. that complicates matters. but then again, the output of the
text is always fine. The suspected memory leaks are never visible in the text as wrong characters.
I hoped the USETAT routine would check any writing out of bounds, and then prevent the writing. etc.
The purpose of the stated procedure is quite common: cut up a long sentence
to fit a limited width window. And it does that fine.
Maybe someone can point out another such procedure so I can learn from it.
I tried to learn from the allegro Gui text-window, but that procedure is more complex since it is aimed at a scrollable text.
I am not experienced in using the debugger in any way actually, but I will try.
richard; Indeed it is one of those goblins!
EDIT: I wrote set_uformat(U_ASCII); after allegro_init(); and the crash in debugmode is now gone.
I also set a breakpoint at the end of the draw_textblok procedure, and I could peek the values of the strings, which look fine to me.
But to my knowledge the coding was fine all along, but I still wonder why it crashed in the first place and if memory leaking is now gone or just unnoticable?