October 10, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andy Friesen | Have you any tips on how to get syntax highlighting working? I've copied the C/C++ settings to a D key under HKCU\Software\Microsoft\Visual Studio\7.0\Text Editor but that's had no effect. :( "Andy Friesen" <andy@ikagames.com> wrote in message news:bm74a3$1e4u$1@digitaldaemon.com... > Walter wrote: > > > I use windbg.exe on it. It works. On linux, I use gdb. > > > > Visual Studio (I've tried 7 and 7.1) works just fine too. Just be sure > to compile with symbolic debug info on, and point the debugger at the > exe like anything else. (-g) > > You can't inspect the members of structs and classes (including 'this'), which is a shame, but you can put watches on local variables, set breakpoints, and step through the program and so forth. > > -- andy > |
October 11, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wilson | Matthew Wilson wrote: > Have you any tips on how to get syntax highlighting working? > > I've copied the C/C++ settings to a D key under > HKCU\Software\Microsoft\Visual Studio\7.0\Text Editor but that's had no > effect. :( > Add a key '.d' to HKLM/Software/Microsoft/VisualStudio/7.x/Languages/File Extensions and copy the value from .c into it. That'll make VS treat D as if it were C++. To add user keywords, create a file called UserType.dat and put it in the same directory as msdev.exe. You can set the colour for the keywords in this file in the 'User Defined Keywords' subsection of the syntax highlighting settings. -- andy |
October 11, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jan-Eric Duden | Jan-Eric Duden wrote:
> so you debug assembler code? or actually d code?
>
> I used the -g option:
>
> c:\dmd\bin\dmd.exe -g -gt -debug -odC:\PROGRA~1\DIDE\Projects\T -version=Win
> dowsXP T.exe "C:\Program Files\DIDE\Projects\T\T.d" -I\dmd\src
>
> started windbg. execute with windbg the .exe and then I just see assembler
> code.
> so what am I doing wrong?
>
D source.
I've always run it through the IDE, so I'm not sure what it's doing on you. Basically, I set up a makefile project, and pointed the debugger at the executable within the project settings.
-- andy
|
October 11, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andy Friesen | > Add a key '.d' to HKLM/Software/Microsoft/VisualStudio/7.x/Languages/File Extensions and copy the value from .c into it. That'll make VS treat D as if it were C++. Nice one. :) > To add user keywords, create a file called UserType.dat and put it in the same directory as msdev.exe. You can set the colour for the keywords in this file in the 'User Defined Keywords' subsection of the syntax highlighting settings. Been doing this one for years, but good to know it'll apply with VS.NET. Thanks for all the info |
October 11, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jan-Eric Duden | "Jan-Eric Duden" <jeduden@whisset.com> wrote in message news:bm76h3> c:\dmd\bin\dmd.exe -g -gt -debug -odC:\PROGRA~1\DIDE\Projects\T -version=Win Don't use -gt for debugging, that is for doing profiling. |
October 11, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hauke Duden | "Hauke Duden" <H.NS.Duden@gmx.net> escreveu na mensagem news:bm6lrg$qtq$1@digitaldaemon.com... > Daniel Yokomiso wrote: > > "Jan-Eric Duden" <jeduden@whisset.com> escreveu na mensagem news:bm5vhd$2uo8$1@digitaldaemon.com... > > > >>Sure, D is high-level, but don't you make mistakes modelling an algorithm? > > > > > > Sure that's where design by contract helps you. You write the preconditions > > and posconditions of every function, and when you test it the compiler will > > do the checks and tell you "The parameter foo should be a list sorted by bar > > but wasn't". If you have the contracts for all of your functions you'll quickly find your bugs. > > Hmmm. Contracts cannot be used to find all kinds of errors. To give one example: inter-thread behavior. Try to find a deadlock by adding contracts to your code. We can divide deadlocks in two kinds: deterministic and unpredictable. If your deadlocks are deterministic they'll always happen so they're easy to figure out and fix. If they are unpredictable the exact condition to trigger them depends on race conditions and debugging mess with the timing so it won't help much here. With some help of the lock classes you can create asserts to ensure that "assert(Thread.current().holds(lock))" before entering or exiting some method call. Also you can have better control and dynamic checking (or static if the compiler let you have dependent int types) if you design safe lock classes: public class Lock { private final int level; public this(int level_) in { assert(level_ >= 0); } body { this.level = level_; } public int getLevel() { return this.level; } public void perform(void delegate() action) { synchronized(this) { action(); } } public Lock and(Lock other) in { assert(getLevel() >= other.getLevel()); } body { return new AndLock(this, other); } } class AndLock : Lock { private final Lock left, right; this(Lock left_, right_) in { assert(left.getLevel() >= right.getLevel()); } body { this.left = left_; this.right = right_; } public int getLevel() { return this.right.getLevel(); } public void perform(void delegate() action) { synchronized(this.left) { synchronized(this.right) { action(); } } } } Lock la = new Lock(2); Lock lb = new Lock(1); void a() { la.and(lb).perform(void delegate() { printf("a"); }); } void b() { lb.and(la).perform(void delegate() { printf("f"); }); } This will cause a assertion error in "b()", because the levels are incorrect. You can make this better by making Lock a template with a int parameter and ensuring the type of the right lock to be correct (less than) at compile time. Also if the Thread class helps you can have the each Thread instance have a level stack attribute and when then lock executes the perform operation you can set the new current level of the Thread. With this the contract of perform can include an in part with a "assert(Thread.current().getLevel() >= getLevel())" to check for deadlocks in other situations. > Besides, contracts have one major drawback. Since the state of a sufficiently complex program is very big, you won't be able to check the consistency of everything after every operation. So basically you need to anticipate what might go wrong in order to be able to write meaningful asserts. That's why you minimize state. State is hell: the more you have it the less reliable your system will be. Local state is ok but everything else should be strictly checked, so you can verify that the locked resources are independent (i.e. no deadlock possible) or they can be used without locks (e.g. atomic or stateless). > And another thing: you can easily get carried away by peppering your code with assertions everywhere. This may be nice from a theoretical point of view, but there IS the problem that when you're writing assertions you don't write code that actually adds functionality. Sure, the code you DO write may be less buggy, but there is a fine line between writing useful assertions and wasting time. A system with a thousand of buggy features do less than a system with one reliable feature. Assertions aren't a "theoretical" tool, they're practical and much better than banging out code that "can't fail because it's too simple". There are lot's of statistics saying that programmers don't write more than x lines of code (where x is usually between 20 and 50) per day, so adding a few assertions won't take much of your time. Even if you are a master coder you will have some periods when you're just thinking about how to write some feature, and in this moment you should write down your assumptions (i.e. pre/postconditions and invariants) as part of the feature design. > Sometimes you just have to have faith that everything will work as expected and use a debugger afterwards if it doesn't. I don't have faith in neither unstated assumptions nor perfect programmers so I can just go on and use a debugger afterwards, because the worst bugs are silent and just keep consuming resources, corrupting data and not working properly. > I'm not saying you shouldn't use assertions. But you need to find a balance between coding time and the ability to prove that the code is bug-free (or at least that the issues you have anticipated do not occur). Assertions make code fail early and fast, because they don't propagate invalid data and corrupt state. It's different from formal proofs or model checking tools, because you write them not to ensure that the code is correct but to ensure that if it's incorrect it'll stop. > In other words: debugging IS necessary ;). Testing is necessary, to ensure that your code paths are covered. Formal proofs are a must have, but most of the times we can afford the time, the cost or the technology to do them. With assertions you may need to debug sometimes, but probably you can make it without debugging tools and just use simple reasoning and assertion failure stack traces. I know I don't need to debug to find my bugs, because the assertions tell me where is its birthplace. > Hauke Best regards, Daniel Yokomiso. "I favour OMG IDL (which I still can't shake off as reading 'Oh my God, IDL!')" - Burton Radons --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.524 / Virus Database: 321 - Release Date: 8/10/2003 |
October 11, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Ok. Ill try that. I got some debugging to work yesterday night.
But I couldn't see the local variables :(
I guess I will need to look further into it.
--
Jan-Eric Duden
"Walter" <walter@digitalmars.com> wrote in message
news:bm9reg$2468$4@digitaldaemon.com...
>
> "Jan-Eric Duden" <jeduden@whisset.com> wrote in message news:bm76h3>
>
c:\dmd\bin\dmd.exe -g -gt -debug -odC:\PROGRA~1\DIDE\Projects\T -version=Win
>
>
> Don't use -gt for debugging, that is for doing profiling.
>
>
|
October 12, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Yokomiso | "Daniel Yokomiso" <daniel_yokomiso@yahoo.com.br> wrote in message news:bma1tm$2cub$1@digitaldaemon.com... > We can divide deadlocks in two kinds: deterministic and unpredictable. If your deadlocks are deterministic they'll always happen so they're easy to figure out and fix. If they are unpredictable the exact condition to trigger > them depends on race conditions and debugging mess with the timing so it won't help much here. That's not true. You're assuming that with the different timing of debugging they won't occur. Usually, in a multi-process environment, things are sufficiently unstable so that conditions that happen in release mode can also happen in debug mode. It may take a few tries, but usually you get to debug your deadlock. > With some help of the lock classes you can create > asserts to ensure that "assert(Thread.current().holds(lock))" before > entering or exiting some method call. Also you can have better control and > dynamic checking (or static if the compiler let you have dependent int > types) if you design safe lock classes: <snipped complicated code> So you suggest that I design the structure of my code around the need to debug deadlocks? The whole point of having the synchronize keyword is to make thread synchronization easy. If you have to go out of your way and wrap everything into Lock classes to get some logs, what use is that? With a debugger I can actually write my code in a way that makes sense from a logical point of view. If you have to write complicated code to make up for missing tool support, things are just messed up. > > Besides, contracts have one major drawback. Since the state of a sufficiently complex program is very big, you won't be able to check the consistency of everything after every operation. So basically you need to anticipate what might go wrong in order to be able to write meaningful asserts. > > > That's why you minimize state. State is hell: the more you have it the less > reliable your system will be. Local state is ok but everything else should be strictly checked, so you can verify that the locked resources are independent (i.e. no deadlock possible) or they can be used without locks (e.g. atomic or stateless). Look at the memory usage of your application. Add to that the size of any temporary files you use and you get some idea on how big the state of a computer program is. Having a state is what software is all about! I realize that you probably use a different definition of the word state, though I'm not quite sure which one that is. "Limiting the state" is sometimes possible if you remove redundancies. But the state of your application would still be huge. As to "keeping it local": I assume you mean that only an object itself should be influenced by its state. However, since objects need to interact in order to form a working program that isn't really feasible. One example: You have some object that performs image filtering. It has a bug that only occurs when the image it filters contains a certain combination of pixel values. The bug doesn't produce a crash, it just creates invalid output. The bug is triggered by the image data you pass to that object, i.e. depends on the state of another object. You cannot necessarily put assertions into the filtering code to make sure that the output is correct, since the correct output can only be determined by the algorithm that you're trying to find a bug in! This is one of the cases where you just need to debug through the algorithm step by step, look at how the values change and hope for an intuition on what is going wrong. > > And another thing: you can easily get carried away by peppering your code with assertions everywhere. This may be nice from a theoretical point of view, but there IS the problem that when you're writing assertions you don't write code that actually adds functionality. Sure, the code you DO write may be less buggy, but there is a fine line between writing useful assertions and wasting time. > > > A system with a thousand of buggy features do less than a system with one reliable feature. Assertions aren't a "theoretical" tool, they're practical > and much better than banging out code that "can't fail because it's too simple". There are lot's of statistics saying that programmers don't write more than x lines of code (where x is usually between 20 and 50) per day, so > adding a few assertions won't take much of your time. Even if you are a master coder you will have some periods when you're just thinking about how > to write some feature, and in this moment you should write down your assumptions (i.e. pre/postconditions and invariants) as part of the feature > design. I didn't advocate not using assertions. But if you want to get rid of debugging you would have to encode every single interdependency between variables into an assertion. If you assume that a programmer only creates 50 lines of code per day and 40 lines of that are assertions, you have a big decrease in productivity. Adding SOME assertions is good practice. Being overly paranoid and checking for everything all the time is just not practical. > Testing is necessary, to ensure that your code paths are covered. Formal proofs are a must have That's where I don't agree. Formal proofs can be major timesinks. If people were going around writing proofs that every single function works correctly, no one would ever get anything done. Same with assertions. As I said before, there is a fine line between using assertions as a useful tool and just using them for the sake of having them. > but most of the times we can afford the time, the > cost or the technology to do them. Right. That's basically what I just said ;). So you DO agree that proofs are not must-haves after all? Hauke |
October 13, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Yokomiso | >
> The code does what you tell it to do. In practice it's very hard to have a bug both in the contract and the code. In this case debugging won't help because you won't know you have a problem. Of course you need to have a contract with an implementation different from the body, otherwise you're just wasting time.
>
Even if we try to put a lot of assertions (and design by contract) in the
code,
we might simply not do some check either because they are difficult to do
(or expensive to execute) or because we forget to do a check or think
the code is so simple that no check are necessary.
When debugging step by step the code, we can often see some errors very easily (a corrupted string, an unexpoected value for a float like 1e20 that also never happen in practice, wrong function called, breakpoint not hit,...)
What I would also like from a debugger would be the ability to very easily add variables to the log... since often we otherwise write a bunch of information on paper while debugging...
Philippe
|
October 13, 2003 Re: Assert stacks | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Mori | As the originator of this thread, I'd just like to say that I believe in assertions, and I also use a debugger. If D had one, I'd use it, even though I've managed well without one so far. I know that D will be more acceptable to the wider dev community when it has a debugger. Arguing for only debugger or only assertions is a bit like arguing one programming language fits all. "Philippe Mori" <philippe_mori@hotmail.com> wrote in message news:bmfa4s$85h$1@digitaldaemon.com... > > > > The code does what you tell it to do. In practice it's very hard to have a > > bug both in the contract and the code. In this case debugging won't help because you won't know you have a problem. Of course you need to have a contract with an implementation different from the body, otherwise you're > > just wasting time. > > > > Even if we try to put a lot of assertions (and design by contract) in the > code, > we might simply not do some check either because they are difficult to do > (or expensive to execute) or because we forget to do a check or think > the code is so simple that no check are necessary. > > When debugging step by step the code, we can often see some errors very easily (a corrupted string, an unexpoected value for a float like 1e20 that also never happen in practice, wrong function called, breakpoint not hit,...) > > What I would also like from a debugger would be the ability to very easily add variables to the log... since often we otherwise write a bunch of information on paper while debugging... > > Philippe > > |
Copyright © 1999-2021 by the D Language Foundation