|
|
This thread is locked; no one can reply to it.
|
1
2
|
| Code review |
|
Adam Kazimierczak
Member #11,613
January 2010
|
Hello! If anyone have some free time and want to help me, Thanks for help, |
|
OnlineCop
Member #7,919
October 2006
|
I'm unable to even get it to compile on Mac. Compiling with debugging, I get a crash within main.cpp, on the call to "langton.start();", it giving me the error: (gdb) r Starting program: /Users/onlinecop/programming/temp/allegro/602869/LILACA/lilaca Reading symbols for shared libraries ...............................................................................+ done Reading symbols for shared libraries . done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0xb0001a70 [Switching to process 3049 thread 0x3213] 0x00003ba7 in _mangled_main () at main.cpp:42 42 langton.start(); (gdb) kill Kill the program being debugged? (y or n) y Current language: auto; currently c++ (gdb) q (My line numberings are different because of some stuff I played around with to get it to work.) Using Allegro 4.2.3.
|
|
Dario ff
Member #10,065
August 2008
|
Same deal here {"name":"600310","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/8\/685a603f1660624021e023b6dc4991df.jpg","w":887,"h":539,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/8\/685a603f1660624021e023b6dc4991df"} I suppose you were lucky enough to don't have a memory crash. EDIT: Can anybody explain me who invented the "this->" crap? I've seen this repeated a lot, and I don't find it any different than calling it without it. EDIT2: This is the culprit: 40void Field::reset() {
41 for(unsigned int i=1; i<=800; i++) { 42 for(unsigned int z=1; z<=800; z++) { 43 this->set_fill(false, i, z);
44 }
45 }
46 this->filled_cells=0;
47}
it should be: 40void Field::reset() {
41 for(unsigned int i=0; i<800; i++) {
42 for(unsigned int z=0; z<800; z++) {
43 this->set_fill(false, i, z);
44 }
45 }
46 this->filled_cells=0;
47}
EDIT3: Remember, a C programmer always starts from 0:
TranslatorHack 2010, a human translation chain in a.cc. |
|
bamccaig
Member #7,536
July 2006
|
dario ff said: Can anybody explain me who invented the "this->" crap? I've seen this repeated a lot, and I don't find it any different than calling it without it.
It's intended to fully qualify the variable, which makes the code more clear and also avoids subtle bugs like C::aab versus ::aaa (AKA, a global variable aaa). It's easy to accidentally type the latter and the compiler won't complain if it's compatible with the context it's used in. If you want to be really sure, you can always go with this->C::aab. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
Dario ff
Member #10,065
August 2008
|
bamccaig said: makes the code more clear
To me it looks really messy. To each it's own I guess bamccaig said: avoids subtle bugs like C::aab versus ::aaa (AKA, a global variable aaa).
You edited fast TranslatorHack 2010, a human translation chain in a.cc. |
|
Audric
Member #907
January 2001
|
The only arguments for "this->" that I can agree with are: |
|
anonymous
Member #8025
November 2006
|
This is a kind of situation where this-> is very convenient (A<T>::foo is non-dependent, hence the compiler needs to be explicitly told that it comes from the template parent) although there are other, more verbose ways: template <class T> struct A { void foo() {} }; template <class T> struct B: public A<T> { void bar() {
|
|
Adam Kazimierczak
Member #11,613
January 2010
|
I thank you all for so fast replies! I know that counting is starting from 0 (I programmed before in asm, php, some bash and perl), I tried to compile my code under windows (on virtual machine), void Field::reset() { for(unsigned int i=0; i<800; i++) { // i=1 and i<800 (from <=800) for(unsigned int z=0; z<800; z++) { // same here this->set_fill(false, i, z); } } this->filled_cells=0; } same for Field::draw_dots. I also received segfault here (Info::draw_info): textprintf_ex(buffer, font, 10, screen->h-20, makecol(255,0,0),-1, "To leave press [ESC]"); So I changed "screen->h-20" to "780" (I am not planning changing resolution in future). Last error is appearing here (at System::start()):
Quote:
Program received signal SIGSEGV, Segmentation fault.
I have no ideas why there is segfault. EDIT: |
|
Dario ff
Member #10,065
August 2008
|
I've made some modifications. One of the most important ones is the one marked with ***. Here. I'll explain:
1const int FIELD_SIZE_W=800;
2const int FIELD_SIZE_H=800;
And anything related to the field used this constant. This way, in case you need to change the size of the field, you won't need to code everything again.
You weren't giving to rand any value, so you always had the same results for your rand calls. I gave it a value related to the system's clock. As you probably know, computers can't handle random, it's just math that appears to give random values, so you've got to give it a value. It's funny that someone based on this in a casino and won the electronic lottery by predicting the numbers with a computer program. TranslatorHack 2010, a human translation chain in a.cc. |
|
Adam Kazimierczak
Member #11,613
January 2010
|
Thanks for your corrections Dario_ff, Adam Kazimierczak said:
Program received signal SIGSEGV, Segmentation fault. By the way, it's very interesting method you used in conditions in loops: for(unsigned int i=0; i!=FIELD_SIZE_W; i++)
|
|
BAF
Member #2,981
December 2002
|
Adam Kazimierczak said:
I know that counting is starting from 0 (I programmed before in asm, php, some bash and perl), So write crappy sloppy code that for unknown reasons solves the segfault you shouldn't have been getting? That's just about the polar opposite of writing good code. Adam Kazimierczak said: for(unsigned int i=0; i!=FIELD_SIZE_W; i++) Should be <, not !=. != will happily let it go beyond FIELD_SIZE_W if somehow i gets incremented past the limit, say by an extra i++ in your loop body or something. |
|
OnlineCop
Member #7,919
October 2006
|
I'd imagine that within the processing pipeline, the advantage of using != is that it simply checks for equality then negates that result; much faster than the <, which subtracts the one from the other and checks whether that sets the overflow/underflow bit, the values are still unequal, etc. The disadvantage is that if you happen to 'hop' over the value you were checking for, you've got either 2^32 or 2^64 more loop iterations to go through before it overflows back to 0 and starts again. Of course by then, you've either segfaulted your application or unplugged your computer for the length of time it's taken...
|
|
Dario ff
Member #10,065
August 2008
|
BAF said: Should be <, not !=. != will happily let it go beyond FIELD_SIZE_W if somehow ii gets incremented past the limit, say by an extra i++ in your loop body or something.
NO, it should be !=. I won't hog the CPU for "safety" when doing loops of 800X800 Thanks to Online cop for the tech explanation. TranslatorHack 2010, a human translation chain in a.cc. |
|
Thomas Fjellstrom
Member #476
June 2000
|
dario ff said: NO, it should be !=. No. It shouldn't. In the off chance the value goes over the right hand side, it will keep looping till it wraps around. it SHOULD be <. So it will always break when i is equal to or greater. Instead of only when it equals the right hand side. Quote: I won't hog the CPU for "safety" when doing loops of 800X800 That makes no sense. -- |
|
Dario ff
Member #10,065
August 2008
|
Yes it does. At least to me... As OnlineCop said, checking for equality is much faster than <. What off chance are you talking about? You know what? Nevermind, I've never had problems with !=. EDIT: Seriously, why are we talking about off chance? I already said that if you put an extra i++ you check the value and break TranslatorHack 2010, a human translation chain in a.cc. |
|
Audric
Member #907
January 2001
|
I'm dubious about the statement on '<' being "much slower than '!=' in the first place (anybody got real-world facts on assembler instructions JNE and JL ?) And in any case, I find it a bad idea(tm) to teach a self-called "newbie C++ programmer" to alter his way of coding an expression. Not before he has completely mastered structured programming; and counting "from 0 included to MAX-1 included" is really part of the basics. |
|
Dario ff
Member #10,065
August 2008
|
Ok ok, use < instead of !=. IDK why I learned this way. He says he didn't do the counting in the right way because he got segfault. Obviously, he screwed up somewhere else, and he was lucky that changing the value didn't crash at start. I'm feeling generous, so I'll read the whole code to see what could be causing the segfault TranslatorHack 2010, a human translation chain in a.cc. |
|
Tobias Dammers
Member #2,604
August 2002
|
dario ff said: As OnlineCop said, checking for equality is much faster than <. Not in any meaningful way. Maybe one or two clock ticks per iteration; on a 2GHz dual-core CPU, that's half a nanosecond. Less than the time a photon travels from the screen to your eye. First of all, the loop overhead is negligible in 99% of all the loops you'll ever write. One or two extra clock ticks on a loop that takes thousands of clock ticks per iteration is literally nothing. If such a loop turns out to burn too much CPU time, see if you can get away with less iterations, with less calls to the loop itself, or with a better algorithm. Only if you are already using the best possible algorithm as sparsely as possible, and you are still having performance problems, consider optimizing code. But before doing so, give the compiler a fair chance of doing it for you (-O2), and when done, be sure to profile so you can be sure the code is really faster. You'd be surprised. Quote: EDIT: Seriously, why are we talking about off chance? I already said that if you put an extra i++ you check the value and break Consider the following code: for (int i = 0; i != 10; ++i) foobar(i); Is this safe or not? You'd be tempted to say "yes", but what if foobar is defined like so: void foobar(int& i) { ++i; }
It is not an off chance, it is a very realistic possible source of bugs that are extremely hard to find. Adam Kazimierczak said:
I know that counting is starting from 0 (I programmed before in asm, php, some bash and perl), This approach is known as shotgun debugging and generally considered bad practice. --- |
|
GullRaDriel
Member #3,861
September 2003
|
What if it is void foobar(int& i) ? Then you should have used C instead of C++ ! And you would have got to use a void foobar( int *i) and a call on foobar( &i ). Which is way more talking than the C++ version who hide the fact that the function can possibly modify the values passed as its parameters. "Code is like shit - it only smells if it is not yours" |
|
Dario ff
Member #10,065
August 2008
|
Ok, I haven't looked at the whole code, but I made some other changes. And because of the massive bitching around here, I replaced != with < (but I think that just for pissing all of you I'll put !(i>=FIELD_SIZE_W) I think the error you have in your VM is because it doesn't support your res. Remember the desktop res must be >= to the window's res. Remember you have a square, 800x800, and it's possible your VM res is lower than that. TranslatorHack 2010, a human translation chain in a.cc. |
|
anonymous
Member #8025
November 2006
|
There seems to be lots of non-sense concerning < vs != A C++ programmer would be quite used to !=, since more often than not he uses iterators, which more often than not are not random access iterators and don't support less-than comparison in the first place. Secondly, if the purpose of the loop is to go from 0 to N with no skipping and things, having it get stuck in an infinite or a very long loop (since the loop counter is unintentionally modified somewhere) is a good thing, since it helps you detect that something is wrong. If the loop just appeared to run normally, it might be harder to find out that the program is not running properly. There seems to be a belief that code that makes efforts to cover up bugs is "safe" compared to code that rings a warning bell as soon as something is wrong. |
|
Adam Kazimierczak
Member #11,613
January 2010
|
Audric, Dario_ff, Thank you all for helping me with segfaults and others! Can we make a little summary? |
|
CursedTyrant
Member #7,080
April 2006
|
Adam Kazimierczak said: "this->" problem and others like that. It's not a problem, it's just unnecessary. --------- |
|
OnlineCop
Member #7,919
October 2006
|
EDIT: I had to change a few other things on my system so it'd work. Notably, you're still creating your screen dimensions at (800, 800) and setting your ant's initial position to (400, 400). But you've defined your array to be 800x600 through use of FIELD_SIZE_W and FIELD_SIZE_H. So change within your langton.cpp the lines: set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 800, 0, 0); to set_gfx_mode(GFX_AUTODETECT_WINDOWED, FIELD_SIZE_W, FIELD_SIZE_H, 0, 0); and both the ant's position and the this->buffer dimensions to the new screen dimensions: this->buffer = create_bitmap(800, 800); ... this->ant.set_position(400, 400); // Center of view to this->buffer = create_bitmap(SCREEN_W, SCREEN_H); ... this->ant.set_position(SCREEN_W / 2, SCREEN_H / 2); // Center of view Then if you change your dimensions again, everything will be fine.
|
|
Audric
Member #907
January 2001
|
Adam: Ah ok, sorry I didn't watch closely. anonymous said: There seems to be a belief that code that makes efforts to cover up bugs is "safe" compared to code that rings a warning bell as soon as something is wrong.
More generally, there are two opposite extremes that are bad: I can cite 2 projects where user safety was more important than programmer convenience: |
|
|
1
2
|