Developer forums (C::B DEVELOPMENT STRICTLY!) > Development
Code::Blocks developint hints
zieQ:
NEVER use "#define" to declare a constant or a macro, especially in header files! This could be tolerated in cpp files but it's a bad habit anyway!
Prefer either an "static const", an "enum" or a template function instead (or better, a non-template inline function)
BAD example:
--- Code: ---#define NO_ERROR 0
#define MIN(A,B) (((A)<(B))?(A):(B))
--- End code ---
GOOD example:
--- Code: ---static const int NO_ERROR = 0;
template <class T> T min(T a, T b) { (a<b)?a:b; }
--- End code ---
This will avoid the side-effect of preprocessor definitions
AkiraDev:
While not being a developer I would like to lend a tip or two.
--- Quote from: zieQ on August 24, 2005, 04:55:52 pm ---Prefer either an "static const", an "enum" or a template function instead (or better, a non-template inline function)
...
GOOD example:
--- Code: ---static const int NO_ERROR = 0;
template <class T> T min(T a, T b) { (a<b)?a:b; }
--- End code ---
--- End quote ---
Why not make the template functions inline? They have no disadvantage with respect to non-template functions. (Yes, old compilers ALWAYS bloated the code before, but not anymore nowadays.) Using this kind of templates is both simple and advisable:
--- Code: ---namespace my {
inline template<typename T> T min(T a, T b) { return a <= b ? a : b; }
inline template<typename T> T max(T a, T b) { return a >= b ? a : b; }
inline template<typename T> T sqr(T a) { return a*a; }
};
--- End code ---
--- Quote ---This will avoid the side-effect of preprocessor definitions
--- End quote ---
Please allow me to complement zieQ's coding style advice by supplying a "textbook example" of how a macro can mess up your code.
Suppose you define a macro that expands your variables to be squared, i.e.:
--- Code: ---#define SQR(A) ((A)*(A))
--- End code ---
Now, suppose you use this macro for a certain expression.
A natural way to write it in a given context would be for example:
--- Code: ---int n = 5;
...
int m = SQR(n++);
--- End code ---
So m should end up being equal to 25 while n finishes as 6, right? Wrong. A macro makes a _textual_ replacement of the expression in the parenthesis by its definition. The compiler replaces what you wrote by
--- Code: ---int m = (n++) * (n++);
--- End code ---
So, in fact, m is equal to 30, and n is equal to 7.
You can easily conclude what might happen with complicated expressions. The consequences of systematically using macros to handle pointers can be much worse, with hard to track segmentation faults.
Needless to say, the above example, with the inline function template shown above, ( my:: sqr() ) would be parsed normally as any function, without any surprises. Type safety is a Good Thing(TM).
Another tip, though maybe not so useful, would be the use of namespaces separation for code clarity. I'd like to see further use of namespaces in the SDK, so I'm posting that as a feature request in sourceforge. Though low priority, I know.
Best regards
grv575:
gdb quickstart:
Some commands to try out...
gdb
file codeblocks (can use tab completion, command history)
run
bt - back trace
frame - list current frame
info source - info on current source file
frame 1 - switch to frame 1
up - go up a stack frame
list - list source code at current position
break - set breakpoint on current function
run - reload debugee
c - continue
break 62 - set breakpoint on line 62
break *0x12345678 - break at address
list 62 - list around line 62
list - list more
list app.cpp:297 - list around line 297 in app.cpp
enter - *** repeat last command ***
help breakpoints - help on breakpoints
info args - show arguments
info break - show breakpoints (i b)
delete 1 2 - delete breakpoints 1 & 2
disable 1 - disable breakpoint 1
info threads - show known threads for the process
info variables - show known variables
finish - execute till ret (out)
interrupt - interrupt execution
kill - kill program
attach 4080 - attach to pid 4080
info frame
info dll
info reg
pwd
cd program files
print x
disp x
undisp x
n - next (over)
s - step (into)
stepi - step one instruction
b 3 x > 5 - make breakpoint 3 conditional (when x > 5)
quit
dissas
x - examine memory
x/s 0x0810267c - examine string at 0x0810267c
printf "%s", *0xbffff970 - printf
whatis x : whatis data type of x
jump 5 : jump to line 5 (set eip here)
grv575:
Wanted to check codeblocks for memory errors. How to compile codeblocks against mpatrol (there's an .exe installer at mingw sourceforge):
1) have gcc include mpatrol.h with each source file:
-include mpatrol.h
2) specify multiple definitions of malloc(), etc are OK linker option:
-Wl,--allow-multiple-definition
3) make sure mpatrol (mpatrolmt) libraries occur before other libraries (which define malloc(), etc):
-lmpatrolmt -limagehlp -lbfd -liberty --lwxmsw26 -lgdi32
So, goto build options
under compiler->other options add
-include mpatrol.h
under linker->other link options add
-Wl,--allow-multiple-definition
under linker->link libraries add (***before all other libraries***)
mpatrolmt
imagehlp
bfd
iberty
(You also need to set the linker settings for the console runner target)
So that should give something like: -lmpatrolmt -limagehlp -lbfd -liberty -lwxmsw26 -lgdi32
when it links.
That should be it. There's a mpatrol.pdf that installs with the mpatrol installer. Basically just run codeblocks.exe and look for a mpatrol.log afterwards. Compiling right now, will test the results later.
Edit: looks like bfd is the wrong object file format for windows. I'll try recompiling mpatrol and see if it works then
Edit: nevermind, it looks like mpatrol doesn't want to work. I just tried the above flags with a simple win32gui app and then putting int* abc = new int[10]; (so that the mpatrol libs are actually linked in)
it gives:
--- Code: ---ERROR: [ILLMEM]: illegal memory read at address 0x00000000
0x00000000 not in heap
call stack
0x00000000 ???
0x0041082C ???
0x0040218C ???
0x00402BF3 ???
0x0041A70F ???
0x0047176D ???
0x004715B7 ???
0x00471399 ???
0x004011E7 ???
0x00401238 ???
0x7C816D4F RegisterWaitForInputIdle+73
--- End code ---
No matter if I delete the memory properly or not. Looks like mpatrol just isn't working right with winxp or something. Any other suggestions for memory checking with mingw?
Edit: OK, I finally figured out mpatrol. Uninstall the mpatrol .exe installer. The precompiled version on the mingw site is "broken":
"I suspect that the gcc C++ ABI has changed since
the downloaded library was built. That would
explain mysterious behavior if true. Try building
the library from source."
http://groups.yahoo.com/group/mpatrol/message/880
Edit: ignore the url below. grab the source at the mingw site which they already patched (better too since it generates dlls).
So download the source:
http://www.cbmamiga.demon.co.uk/mpatrol/
--- Code: ---extract to c:\ and then open an MSYS prompt and do:
cd /usr; mkdir local; ln -s "/c/MinGW/include" include; ln -s "/c/MinGW/lib" lib
vi /etc/profile
export LD_LIBRARY_PATH = "/usr/local/lib:$LD_LIBRARY_PATH"
source /etc/profile
place the attached patch in c:\ and change to the extracted mpatrol directory:
cd /c/mpatrol
patch -p1 -i ../mpatrol-1.4.8-mingw.patch.txt
cd build/unix
make clean
make all
copy generated files to the right place
create
c:\MinGW\include\mpatrol
c:\MinGW\doc\mpatrol
cp *.h "/c/MinGW/include/mpatrol"
mv "/c/MinGW/include/mpatrol/{mpatrol.h,mpalloc.h,mpdebug.h}" "/c/MinGW/include"
cp *.lib *.exp *.so "/c/MinGW/lib"
copy the contents of the mpatrol\doc directory to c:\MinGW\doc\mpatrol
--- End code ---
All set. To test build a new Win32GUI application.
--- Code: ---Add
int* abc = new int[10];
after the case WM_DESTROY:
(compare with later adding delete[] abc; as well. or even just delete abc; which leaks but doesn't crash... but mpatrol catches this)
Next goto build options:
check produce debugging symbols (-g)
compiler->other options =
-include mpatrol.h
linker->link libraries =
mpatrol
imagehlp
bfd
iberty
gdi32
user32
kernel32
other link options is blank since we are linking the static libmpatrol.a (dynamic .so one requires -Wl,--allow-multiple-definition)
rebuild and then open a cmd prompt
set MPATROL_OPTIONS=PROF LEAKTABLE
(see the documentation...)
and run:
Win32GUI.exe
exit the app and then look at:
mpatrol.log
also try at the cmd prompt:
mprof
--- End code ---
you should see...
top 2 unfreed memory entries in leak table:
--- Code: --- bytes count location
-------- ------ --------
60 1 ___w32_sharedptr_initialize
40 1 main.cpp line 85
100 2 total
--- End code ---
cool, huh? Shows you exactly where you put a new[] and then later never delete[]ed.
[attachment deleted by admin]
grv575:
Debugging on linux:
First, it's best to compile wxWidgets with debug info. This provides assertions, etc (which can be turned on/off in the $(WXDIR)/lib/wx/include/gtk2-ansi-release-2.6/wx/setup.h file).
Next, also compile codeblocks with debug info. (--enable-debug configure flag)
Turn on core dumping
edit ~/.bash_profile
add
ulimit -c unlimited
save and do
source ~/.bash_profile
change to the codeblocks bin directory (add2line currently needs to be in the same directory as the codeblocks binary to load debugging symbols):
cd /usr/local/bin
./codeblocks
now when an assertion triggers, you can hit yes to stop the program. it will dump core (also when the program crashes it dumps core...)
you can then load the core dump with all debugging symbols and stack trace information using:
gdb codeblocks core
then the usual
bt
frame 5
list
print var
etc.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version