I'm currently porting the VMS Pascal version of the classic Moria game, but I'm not sure if I'm understanding the limits of if/then statements (I've never programmed in Pascal before).
My understanding so far is that with no begin/end, then an if/then block only encloses one following statement. If that's the case, then in the following code;
if (i4 > 0) then
with inventory[i4] do
begin
objdes(out_val,i4,false);
msg_print('Your ' + out_val + ' glows faintly!');
if (enchant(toac)) then
begin
flags := uand(%X'7FFFFFFF',flags);
py_bonuses(blank_treasure,0);
end
else
msg_print('The enchantment fails...');
end;
ident := true;
the ident := true; would be outside of the if (tval > 0) then block, meaning that even if i4 is 0, ident would still be set to true.
If that is correct, then does it mean the following code from UMoria (a C port) is wrong?
i_ptr = &inventory[INVEN_WIELD];
if (i_ptr->tval != TV_NOTHING) {
objdes(tmp_str, i_ptr, FALSE);
(void) sprintf(out_val, "Your %s glows faintly!", tmp_str);
msg_print(out_val);
if (enchant(&i_ptr->tohit, 10))
{
i_ptr->flags &= ~TR_CURSED;
calc_bonuses();
}
else
msg_print("The enchantment fails.");
ident = TRUE;
}
...as the ident = TRUE; is inside the if block.
I've seen similar examples in several places -- I guess it's possible that these were changed for the C port -- but I'm hoping to get clarification before I change too much code.
Your assessment of the flow control is correct. However, the assignment of indent to true in the original Pascal code most likely was meant to be in the if/then statement due to the indentation.
This is why I always run an auto indentation on the source code in an IDE. It flushes out these bugs. (Python is an over reaction to this as I've seen indentation bugs in it and its not as amenable to automatic IDE help.)
I suspect the C port to be correct if someone proofread it and tested it.
Test driven development helps here as it helps define what is truly intended.
Related
While using Visual Studio 2017 v15.9.35
I noticed that for functions with long if/else chains the indentation would break at some point. After some experimentation I was able to figure out why; when the if/else chain is over 100 lines in length (from the first if() line) the formatting breaks.
//under 100 lines with expected behavior
void test()
{
int x = 10;
if(x == 10)
{
x = 11;
}
else //when you press enter twice the closing bracket is in the correct position
{
x = 12;
}
}
//>= 100 lines
void test()
{
int x = 10;
if(x == 10)
{
x = 11;
x = 11;
... repeat 95 more times (97 in total)
}
else //when you press enter twice the formatting breaks
{
x=12;
}
}
After this happens all new lines of code are misaligned by 1 tab which gets really annoying. The example I gave is unrealistic but easy to reproduce, in a real scenario just reaching 100+ lines cumulatively (not just in a single block) causes the same behavior. I was wondering if this is a bug or if there is some setting I can adjust or plugin I can install to get the correct behavior. I'm aware that refactoring the code by moving the block code into separate functions to reduce the overall length is an option too, but this is not always the most desirable solution. I was going to report this on https://developercommunity.visualstudio.com/ as well, but I'm not sure if 2017 is still supported.
Also just to reiterate, the question is: Is this a bug or is there some setting I can adjust or plugin I can install to get the correct behavior.
After reporting this issue to the Microsoft team it was noted that this is a known issue. This confirms that it is indeed a bug and not something settings related.
https://developercommunity.visualstudio.com/t/Inconsistent-auto-tabulation-behavior-wh/1429071
While looking through some other reports that were also flagged as duplicates I found this partial solution for VS 2019.
https://developercommunity2.visualstudio.com/t/Visual-Studio-2019-and-C:-Indenting-on/986698
The only way I’ve found to stop this in the Options is to change the
Tabs->Indent from Smart to Block. But unfortunately this also disables
other options that I do want, such as formatting a section when I type
“}” or “;”.
I have a nondeterministic memory corruption problem. Because it's not always the same address, and it occurs only rarely, I can't simply watchpoint it with gdb.
The problem is a value changes between point A and point B in my program. The only thing that is supposed to change it is point C, which does not run in that time (at least not for the specific instance that experiences the unexpected modification).
What I'd like to do is something like mprotect the value at point A so the machine will trap if it is modified and unprotected it again around the intentional modification at point C. Of course, mprotect is not meant to be taken literally as I need it to work with word granularity.
Simply watchpointing at point A manually with gdb is far too much toil, the frequency of the problem is only about one per thousand.
Ideally, I would like a stack trace at the point that modifies it.
Any ideas?
Update: I just found out about rr http://rr-project.org/, a tool that can allegedly "determinize" non-determinism problems. I'm going to give it a go.
Update2: Well that was a short trip:
[FATAL /build/rr-jR8ti5/rr-4.1.0/src/PerfCounters.cc:167:init_attributes() errno: 0 'Success']
-> Microarchitecture `Intel Merom' currently unsupported.
You are experiencing undefined behavior and it's being caused somewhere else, debugging this is really hard.
Since you are apparently on Linux, use valgrind and it will help you a lot. If you are not on Linux or (OS X which is also supported by valgrind), search for equivalent memory error detection software for your system.
I found that it isn't that difficult to script gdb in a scripting language that you know (in my case, Ruby). This cuts down on the need to learn how to make proper gdb scripts!
The API between the target program and the script is that the target program has a blank function called my_breakpoint that accepts a single machine word as an argument. Calling my_breakpoint(1); my_breakpoint(addr); adds an address to the watch list while the same thing with the constant 2 removes an address from the watch list.
To use this, you need to start gdbserver 127.0.0.1:7117 myapp myargs, and then launch the following script. When the script detects a problem, it disconnects cleanly from gdbserver so that you can reconnect another instance of gdb with gdb -ex 'target remote 127.0.0.1:7117' and off you go.
Note that it's extremely slow to use software watchpoints like this; maybe someday something like this can implemented as valgrind tool.
#!/usr/bin/env ruby
system("rm -f /tmp/gdb_i /tmp/gdb_o");
system("mkfifo /tmp/gdb_i /tmp/gdb_o");
system("killall -w gdb");
system("gdb -ex 'target remote 127.0.0.1:7117' </tmp/gdb_i >/tmp/gdb_o &");
$fo = File.open("/tmp/gdb_i", "wb");
$fi = File.open("/tmp/gdb_o", "rb");
def gdb_put(l)
$stderr.puts("gdb_out: #{l}");
$fo.write((l + "\n"));
$fo.flush;
end
gdb_put("b my_breakpoint");
gdb_put("set can-use-hw-watchpoints 0");
gdb_put("c");
$state = 0;
$watchpoint_ctr = 1; # start at 1 so the 1st watchpoint gets 2, etc. this is because the breakpoint gets 1.
$watchpoint_nr = {};
def gdb_got_my_breakpoint(x)
$stderr.puts("my_breakpoint #{x}");
if ((x == 1) || (x == 2))
raise if ($state != 0);
$state = x;
gdb_put("c");
else
if ($state == 1)
raise if ($watchpoint_nr[x].nil?.!);
$watchpoint_nr[x] = ($watchpoint_ctr += 1);
gdb_put("watch *#{x}");
elsif ($state == 2)
nr = $watchpoint_nr[x];
if (nr.nil?)
$stderr.puts("WARNING: ignoring delete request for watchpoint #{x} not previously established");
else
gdb_put("delete #{nr}");
$watchpoint_nr.delete(x);
end
end
$state = 0;
gdb_put("info breakpoints");
$stderr.puts("INFO: my current notion: #{$watchpoint_nr}");
gdb_put("c");
end
end
def gdb_got(l)
t = l.split;
if ((t[0] == "Breakpoint") && (t[2] == "my_breakpoint"))
gdb_got_my_breakpoint(t[3][3..-2].to_i);
end
if (l.start_with?("Program received signal ") || l.start_with?("Watchpoint "))
gdb_put("disconnect");
gdb_put("q");
sleep;
end
end
while (l = $fi.gets)
l = l.strip;
$stderr.puts("gdb_inp: #{l}");
gdb_got(l);
end
This is my first post on stack overflow, so please forgive me for any mistakes.
I learned c++ with Xcode and recently started working with a group that uses Emacs. This group has a huge code in c++ and so I did a CMake interface to generate a project in Xcode. What happened is that the code appears badly indented in Xcode. For instance, these lines in emacs:
if ( argc > 4 ) {
std::string argument( argv[arg_index++] );
// NOTE: file_name should NOT be "aboveCrack" or "belowCrack"
if ( argument == "aboveCrack" ) {
surf_to_draw = CrackMn3DGraphDX2::EAboveSurface;
}
else if ( argument == "belowCrack" ) {
surf_to_draw = CrackMn3DGraphDX2::EBelowSurface;
}
else {
// argument 4 is comp. crack surface output name
got_file_name = true;
postCompSurface_file_name = argument;
}
}
if ( !got_file_name && argc > 5 ) {
got_file_name = true;
postCompSurface_file_name = argv[arg_index++];
if ( argc > 6 ) {
// get comp. crack surface output style
postCompSurface_style = argv[arg_index++];
}
}
Look like this in Xcode:
if ( argc > 4 ) {
std::string argument( argv[arg_index++] );
// NOTE: file_name should NOT be "aboveCrack" or "belowCrack"
if ( argument == "aboveCrack" ) {
surf_to_draw = CrackMn3DGraphDX2::EAboveSurface;
}
else if ( argument == "belowCrack" ) {
surf_to_draw = CrackMn3DGraphDX2::EBelowSurface;
}
else {
// argument 4 is comp. crack surface output name
got_file_name = true;
postCompSurface_file_name = argument;
}
}
if ( !got_file_name && argc > 5 ) {
got_file_name = true;
postCompSurface_file_name = argv[arg_index++];
if ( argc > 6 ) {
// get comp. crack surface output style
postCompSurface_style = argv[arg_index++];
}
}
Which is impossible to program with.
I searched and apparently it has something to do with the tabs in Emacs. Based on this, one fix I could find was to open each file in Emacs and do C-x h (mark all) followed by M-x untabify. This transforms the tabs in spaces and everything looks good in Xcode.
The problems with this idea are that it requires to change the files one by one and it won't stop this from happening again in the future.
Therefore, my question is: is there a way to open the Emacs indented files in Xcode preserving the indentation?
Many thanks!
Nathan Shauer
The first setting that you need to put in your .emacs is: (setq-default indent-tabs-mode nil). This will make sure emacs uses spaces instead of tabs for indentation.
Also, I created a tiny function:
(defun rag/untabify-buffer ()
;; get rid of all the tabs in a buffer
(interactive)
(untabify (point-min) (point-max))
nil)
Add this to before-save-hook and this will make sure all the files will be untabified when you make a change and save a file. Once you've untabified all files, you can remove the hook
No. While it is possible to use emacs to make these changes or even a number of other tools which can automate such changes, it won't really fix your problem as you will likely have to do it every time you check out the code from version control. Depending on the version control system used, it is also possible that doing such formatting changes will result in the code appearing to be modified, which will result in larger checkins and make other useful tools less useful because more will appear to have been changed than was actually changed. This will likely frustrate other project members.
There are two basic approaches, but one depends on the version control solution being used by the project. The first solution is to get the project to agree on a coding standard which specifies either that normal spaces must be used for indentation or that tabs are to be used. The problems you are seeing are primarily due to a mix. Emacs is able to handle this sort of mixed formatting quite well, but other editors, like Xcode are not so smart.
The other approach, which can work quite well because it doesn't rely on everyone following the standard is to configure the version control system to translate tabs as part of the checkin process into spaces. How this is done depends on the version control system being used.
Essentially, this is a problem which needs to be addressed at the project or version control level. Anything you do will only need to be repeated every time you do a fresh pull from version control for any files which have been modified. Fix it at the repository level and the issue will go away.
Is there any way to print to a text file the code that it's being executed for debugging purposes?
for example:
if (i == 1)
{
a = true;
}
else
{
a = false
}
So when i = 1 we print to a text file:
if (i == 1)
{
a = true;
}
else
and when i != 1 we print to the text file
if (i == 1)
else
{
a = false
}
I am not saying that this is a good practice. I know that gdb and other tools are much better to debug code so please don't get mad if you think that it's an awful idea. I was just wondering if it can be done. It would be like adding a printf after every line so we only print the lines that get executed. No thread save or anything like that.
I think what you want hasn't anything to do with debugging in the first place, but with unit testing and test coverage:
You'll need to create unit tests (e.g. using googletest) for your code and compile it with code coverage options switched on (e.g. --coverage for GCC). Then you can use a tool to create a coverage report (e.g. lcov/genhtml for the mentioned toolchain).
The unit tests will control the input for your cases (i = 1/0).
For debugging purposes I would say it is not practical. Yes, you can do a printf before/after each line of execution, but that would just clog up your program. Also, if you're talking about debugging the execution of loops, you will end up printing a bunch of junk over and over again and would have to look forever to find potential bugs. In short, use breakpoints.
However, from a theoretical standpoint, it is possible to create a program that outputs itself. This is a little different from what you want because you only need parts of your program, but my best guess is that with a little modification it can be done.
I'm trying to debug a method which among other things, adds items to a list which is local to the method.
However, every so often the list size gets set to zero "midstream". I would like to set the debugger to break when the list size becomes zero, but I don't know how to, and would appreciate any pointers on how to do this.
Thanks.
Why not use conditional breakpoints?
http://blogs.msdn.com/saraford/archive/2008/06/17/did-you-know-you-can-set-conditional-breakpoints-239.aspx
in C#
if(theList.Count == 0){
//do something meaningless here .e.g.
int i = 1; // << set your breakpoint here
}
in VB.NET
If theList.Count = 0 Then
'do something meaningless here .e.g.
Dim i = 1; ' << set your breakpoint here
End If
For completeness sake, here's the C++ version:
if(theList->Count == 0){
//do something meaningless here .e.g.
int i = 1; // << set your breakpoint here
}
I can give a partial answer for Visual Studio 2005. If you open the "Breakpoints" window (Alt + F9) you get a list of breakpoints. Right-click on the breakpoint you want, and choose "Condition." Then put in the condition you want.
You have already got both major options suggested:
1. Conditional breakpoints
2. Code to check for the wrong value, and with a breakpoint if so happens
The first option is the easiest and best, but on large loops it is unfortunately really slow! If you loop 100's of thousands iterations the only real option is #2. In option #1 the cpu break into the debugger on each iteration, then it evaluates the condition and if the condition for breaking is false it just continiues execution of the program. This is slow when it happens thousands of times, it is actually slow if you loop just 1000 times (depending on hardware of course)
As I suspect you really want an "global" breakpoint condition that should break the program if a certain condition is met (array size == 0), unfortunately that does not exist to my knowledge. I have made a debugging function that checks the condition, and if it is true it does something meaningless that I have a breakpoint set to (i.e. option 2), then I call that function frequently where I suspect the original fails. When the system breaks you can use the call stack to identify the faulty location.