gdb user defined command throws error with argument - gdb

I am trying to write user defined command. I followed the adder example here: https://sourceware.org/gdb/onlinedocs/gdb/Define.html
(gdb) define adder
Type commands for definition of "adder".
End with a line saying just "end".
> set $i = 0
> set $sum = 0
> while $i < $argc
> eval "set $sum = $sum + $arg%d", $i
> set $i = $i + 1
> end
> print $sum
>end
(gdb) adder 1 2 3
Argument to arithmetic operation not a number or boolean.
(gdb)
The syntax looks correct to me. Why am I getting error of Argument to arithmetic operation not a number or boolean.?

Related

Windows batch if statement influenced by statements in the if block

When I execute the following Windows batch script on Windows Server 2012:
#echo off
SET v=()
IF 1 == 2 (
echo hi
echo %v:~0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo %v:0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
I get the following output:
1 equals 2
1 does not equal 2
1 does not equal 2
Can anybody tell me why this happens? I don't want to go into the block starting with echo hi even if the value of v is ().
I'm not quite sure what your intention is, but here's how I think your issue can be fixed.
The variable %v% is parsed before the IF command is run, and that contains a problematic closing parenthesis. What happens therefore is that the code reads, echo %v:~0% as echo ( and closes the IF with ) It then parses the next line which is echo 1 equals 2, and prints it as expected.
To prevent that, either escape that parenthesis, when you define that variable:
#echo off
SET "v=(^)"
IF 1 == 2 (
echo hi
echo %v:~0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo %v:0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
Or, better still enable delayed expansion, so that the variable content is not parsed before the command is run, only when it is:
#echo off
SET "v=()"
setlocal enabledelayedexpansion
IF 1 == 2 (
echo hi
echo !v:~0!
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo !v:0!
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)

why is this bash code so slow in comparison to corresponding cpp code?

I am new to OS as it was introduced to us very recently.
we have bash code to run as our lap experiments.
my last task was to code a program to print whether a number is prime or not.
i coded it first in cpp because i am comfortable in cpp. and then coded same in bash after lot of googling. but my bash code is very slower than the cpp code.
I wrote a cpp code to check whether a number is prime or not.
cpp code :
#include <iostream>
using namespace std;
bool isprime(int a) {
if (a == 2 || a == 3)
return true;
if (a % 2 == 0)
return false;
if (a % 3 == 0)
return false;
for (int i = 1; (6 * i - 1) * (6 * i - i) <= a; ++i) {
if (a % (6 * i - 1) == 0)
return false;
if (a % (6 * i + 1) == 0)
return false;
}
return true;
}
int main() {
int n;
cin >> n;
cout << ((isprime(n)) ? "Prime" : "Not Prime") << endl;
return 0;
}
I wrote the same code in bash (linux):
read num
f=1
if test $num -eq 2
then f=1
elif test $num -eq 3
then f=1
elif test `expr $num % 2` -eq 0
then f=0
elif test `expr $num % 3` -eq 0
then f=0
else
for (( i=1; $((`expr i\*6-1`))**2 <= num; i++))
do
t=`expr $i \* 6 - 1`
if test `expr $num % $t` -eq 0
then
f=0
fi
t=`expr $i \* 6 + 1`
if test `expr $num % $t` -eq 0
then
f=0
fi
done
fi
if test $f -eq 1
then
echo 'Prime'
else
echo 'Not-Prime'
fi
but cpp code is very fast and bash code is very slow
here is terminal input and output
a#a:~/Cp$ cat > input
1000000007
^?^C
a#a:~/Cp$ time ./a.out < input
Prime
real 0m0.003s
user 0m0.003s
sys 0m0.000s
a#a:~/Cp$ time ./prog.sh <input
^C
real 0m8.258s
user 0m5.906s
sys 0m2.794s
a#a:~/Cp$ # I interrupted the execution.
I have no idea why is this happening?
The C++ as other compiled languages have for sure a better performance with respect to interpreted languages like bash, sh, python.
This because when you use a compiled program, only a process is launched, while when you run an interpreted program it instatiates a great number of subprocesses also for basic operation.
So is trivial that c++ program is faster than the bash one.
There's not much to the code other than tests and math, but you are spending a lot of time on those individual bash-level commands.
We can eliminate the overhead of the bash-level command/process calls by pushing all of the code down into a single awk call.
Here's a verbose copy of your bash code running in awk:
$ cat isprime
#!/usr/bin/bash
input=${1} # user's input number;
# OP will probably want to add some logic to validate the input as numeric
awk -v num="${input}" ' # pass input number to awk in 'num' variable
BEGIN { f=1 } # init our flag
{ if ( num == 2 ) { f=1 }
else if ( num == 3 ) { f=1 }
else if ( (num % 2) == 0 ) { f=0 }
else if ( (num % 3) == 0 ) { f=0 }
else for ( i=1 ; (i*6-1)**2 <= num ; i++ ) {
t=(i*6-1)
if ( (num % t) == 0 ) { f=0 ; break } # for non-prime numbers we can abort the for loop to save some cycles
t=(i*6+1)
if ( (num % t) == 0 ) { f=0 ; break } # for non-prime numbers we can abort the for loop to save some cycles
}
}
END { msg="Prime"
if ( f == 0 ) { msg="Not-Prime" }
print msg # print our finding to stdout
}
' <<< "" # awk needs a 'file' to work on so we'll feed it an empty here-string
Timing this script for the sample number '1000000007` gives us:
$ time ./isprime 1000000007
Prime
real 0m0.262s
user 0m0.061s
sys 0m0.170s
NOTE: Repeated runs of the above test showed real run times ranging from 0m0.082s to 0m0.262s; the wide range of numbers is due to me running the above under cygwin in a Windows7 VM; I would expect more consistent run times (towards the lower end?) in a linux environment; ymmv ...
And a non-prime test:
$ time ./isprime 1000000006
Not-Prime
real 0m0.125s
user 0m0.015s
sys 0m0.045s
Not as fast as the C++ program but definitely a good bit faster than processing all those individual bash-level test/process calls.
There are a few awkisms that could be added to shave some additional time off the run but for the sake of this answer I wanted to make it as easy as possible to compare the code with the OPs C++/shell code snippets.
The usefulness of this awk solution will be based on the size of the input (number).
Testing the above against some 20-24 digit primes shows this awk solution immediately bails on the %2==0 or %3==0 tests. This comes down to numerical limits in a basic awk implementation.
From my man pages for awk:
-M
--bignum
Force arbitrary precision arithmetic on numbers. This option has no effect if gawk is not compiled to
use the GNU MPFR and GMP libraries. (In such a case, gawk issues a warning.)
Adding the -M flag to the above awk solution does allow the script to work on a 21-digit prime, but it's not fast ...
awk -M -v num="${input}" ' ...
# and then:
$ time ./isprime 998887766553300224411
... as I type this it's going on 8 minutess of 100% cpu utilization (total of a single core)
... aborted after 13 minutes
While I have no doubt this awk solution would eventually complete, the basic fact is it's going to take a looooong time to count from 1 to a 21-digit number by increments of 1 (i++) (this will be true for any implementation whether it be bash, awk, C++, etc).
For really large numbers I'd be looking at other (much more complex) algorithms for verifying a number is a prime.
This is a much faster bash version
read num
f=1
if test $num -eq 2 -o $num -eq 3
then f=1
elif (( num % 2 == 0 || num % 3 == 0 ))
then f=0
else
for (( i=1; ; i++)); do
t=$((i * 6 - 1))
(( t * t > num )) && break
(( num % t == 0 || num % (i * 6 + 1) == 0 )) && { f=0; break; }
done
fi
if test $f -eq 1; then
echo 'Prime'
else
echo 'Not-Prime'
fi
All calls to expr have been removed.
time bash test.sh <<< 1000000007
Prime
real 0m0.128s
user 0m0.000s
sys 0m0.094s

How to turn off printing the commands just executed

I am not sure how to call it, basically I have such user defined command:
define dump_stack
set $i = stackTop
while $i >= 0
if stackPtr[1]->bytes == 0
printf "0x%x\n", stackPtr[$i]
else
printf "0x%x:%s\n", stackPtr[$i], stackPtr[$i]->bytes
end
set $i = $i - 1
end
end
When I call this command inside gdb, I see this:
(gdb) dump_stack
+dump_stack
++set $i = stackTop
++while $i >= 0
+++if stackPtr[1]->bytes == 0
++++printf "0x%x\n", stackPtr[$i]
0x55756f40
+++set $i = $i - 1
+++if stackPtr[1]->bytes == 0
++++printf "0x%x\n", stackPtr[$i]
0x5576ba50
+++set $i = $i - 1
+++if stackPtr[1]->bytes == 0
++++printf "0x%x\n", stackPtr[$i]
0x5576ac70
+++set $i = $i - 1
+++if stackPtr[1]->bytes == 0
++++printf "0x%x\n", stackPtr[$i]
0x5576ac10
+++set $i = $i - 1
You can see all those lines starting with "+" are very noisy.
What is the command to turn it off so that, for the above, I only see:
0x55756f40
0x5576ba50
0x5576ac70
0x5576ac10
Thanks!
[UPDATE] Find the answer: set trace-commands off

How to break on entering and leaving a function in GDB from bpx commands?

So when using the GDB prompt I can use break foobar to break upon entering function foobar. Then I can assign commands to that breakpoint, such as:
set $i = 0
commands 1
silent
printf "Before foobar: %d\n", $i
set $i = $i + 1
end
However, from these commands how would I proceed until the end of the function (on the prompt it's finish) and then simply output another line (printf "Before foobar: %d\n", $i) and continue.
I tried using this from .gdbinit:
set $i = 0
commands 1
silent
printf "Before foobar: %d\n", $i
set $i = $i + 1
finish
printf "After foobar: %d\n", $i
end
But it simply never prints anything for the second printf, presumably because of the "mode" in which GDB is during commands.
Can anyone tell me whether what I want is at all possible (GDB version is 7.7.1) and if it is, how to accomplish it?

How to check if a variable (e.g. $3) exists so that I don't get a warning about "uninitialized value"?

I am trying to run a script on a .csv file that converts sizes in feet and inches to separate columns of width in inches and height in inches.
It works fine when not using strict mode, but returns a warning message when use warnings; is set.
My problem occurs here:
if ($data[$index_num] =~ /(\d+)'( (\d+)'')? x (\d+)'( (\d+)'')?/) {
my $width = $1*12+$3;
my $height = $4*12+$6;
...
}
Since sometimes the size could be 5' x 8' the special variables $3 and $6 do not exist.
All possible size formats are as follows:
5' 1'' x 6' 7'' (All Single Digits)
10' 1'' x 5' 10'' (Combination of Single and Double Digits)
5' x 8' (No Inches)
4' 6'' x 7' (Combination of No Inches and Inches)
The warning I receive is:
Use of uninitialized value $6 in addition (+) at script.pl line 47, line 567.
This is happening in either case 3 or 4 where the inches are missing on either the width or height.
How can I check to see if either $3 or $6 exists before trying to use them?
You can use defined function:
my $height;
if(defined($6))
{
$height = $4*12+$6;
}
else
{
$height = $4*12;
}
First, let's get rid of useless captures:
/(\d+)'(?: (\d+)'')? x (\d+)'(?: (\d+)'')?/
Captures that didn't match are set to undef, so you can used defined or //.
my $width = $1 * 12 + ($2 // 0);
my $height = $3 * 12 + ($4 // 0);
// was introduced in Perl 5.10. For backwards compatibility, you can use the following:
my $width = $1 * 12 + ($2 || 0);
my $height = $3 * 12 + ($4 || 0);
The second version uses zero when $2 (or $4) is false (undef, zero, or empty string) rather than undef, but that's perfectly fine here.
If you just want to test for a number AND you're happy to calculate a result when there is no match then you could say:
if ($data[$index_num] =~ /(\d+)\'( (\d+)\'\')? x (\d+)\'( (\d+)\'\')?/) {
my $width = ( $1 || 0 ) * 12 + ( $3 || 0 );
my $height = ( $4 || 0 ) * 12 + ( $6 || 0 );
...
}
Why does this work? Because if, say, $1 is undefined, then ($1 || 0) returns the right-hand side, or 0. Likewise if $1 is zero then the left-hand-side of the OR condition will also fail but return 0 nonetheless. And if $1 is non-zero and defined then the left-hand-side will be returned ($1).
If you're going to use the || technique then ensure you put the left-hand and right-hand sides inside parenthesis to avoid operator-precedence side effects.