Gotchas: Difference between revisions

14,283 bytes added ,  5 months ago
m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(26 intermediate revisions by 7 users not shown)
Line 1:
{{draft task}}
 
;Definition
Line 9:
=={{header|6502 Assembly}}==
===Numeric Literals===
Integer literals used in instruction operands need to begin with a #, otherwise, the CPU considers them to be a pointer to memory, which will be dereferenced. This applies to any integer representation, even ASCII.
<syntaxhighlight lang="6502asm">LDA 'J' ;load the 8-bit value stored at memory address 0x004A into the accumulator.
OR 3 ;bitwise OR the accumulator with the 8-bit value stored at memory address 0x0003
Line 19:
 
<syntaxhighlight lang="6502asm">byte $45 ;this is the literal constant value $45, not "the value stored at memory address 0x0045"</syntaxhighlight>
 
 
===Memory-Mapped Hardware===
Line 46 ⟶ 45:
SBC #4 ;eight minus four</syntaxhighlight>
 
===Adding/Subtracting With Carry===
The 6502 (and even its revisions) have ''no way to add or subtract without involving the carry flag.'' The "carry" is essentially the same as "carrying the one" that we all learned in elementary school arithmetic. <code>ADC</code> adds an extra 1 if the carry flag was set when the <code>ADC</code> was executed. <code>SBC</code> subtracts an extra 1 if the carry was ''clear'' when the <code>SBC</code> was executed (as stated before, on most other CPUs the equivalent of <code>SBC</code> behaves the opposite to the 6502).
 
Line 101 ⟶ 100:
=={{header|68000 Assembly}}==
===Numeric Literals===
Integer literals used in instruction operands need to begin with a #, otherwise, the CPU considers them to be a pointer to memory that will be dereferenced. This applies to any integer representation, even ASCII.
<syntaxhighlight lang="68000devpac">MOVE.L $12345678,D0 ;move the 32-bit value stored at memory address $12345678 into D0
MOVE.L #$12345678,D0 ;load the D0 register with the constant value $12345678</syntaxhighlight>
Line 110 ⟶ 109:
 
===LEA Does Not Dereference===
When dereferencing a pointer using an address register, it is necessary to use parentheses. For these examples,
<syntaxhighlight lang="68000devpac">MOVEA.L #$A04000,A0 ;load the address $A04000 into A0
MOVE.L A0,D0 ;move the quantity $A04000 into D0
Line 120 ⟶ 119:
<syntaxhighlight lang="68000devpac">LEA $A04000,A0 ;effectively MOVEA.L #$A04000,A0
LEA (4,A0),A0 ;effectively ADDA.L #4,A0</syntaxhighlight>
 
Also, as we have seen before, constant pointers do not need parentheses and are automatically dereferenced.
 
===Partitioned Registers===
Line 157 ⟶ 158:
EXT.L D1 ;D1 = $FFFF8000</syntaxhighlight>
 
=={{header|MIPS AssemblyC}}==
===Delay Slotsif(a=b)===
This is an easy mistake to make if you're in a hurry. The ''assignment operator'' <code>=</code> is different from the ''equality comparison operator'' <code>==</code>. Therefore you have the following similar looking but vastly different statements, both of which are valid.
Due to the way MIPS's instruction pipeline works, an instruction placed after a branch instruction is executed during the branch, ''even if the branch is taken.''
 
<syntaxhighlight lang="mipsC">moveif(a=b){} $t0//assigns to "a" the value of "b". Then,$zero if "a" is nonzero, the code in the ;loadcurly 0braces intois $t0run.
beqz $t0,myLabel ;branch if $t0 equals 0
addiu $t0,1 ;add 1 to $t0. This happens during the branch, even though the program counter never reaches this instruction.</syntaxhighlight>
 
if(a==b){} //runs the code in the curly braces if and only if the value of "a" equals the value of "b".</syntaxhighlight>
Now, you may think that the 1 gets added first and therefore the branch doesn't take place since the conditions are no longer true. However, this is '''not the case.''' The condition is already "locked in" by the time <code>addiu $t0,1</code> finishes. If you compared again immediately upon arriving at <code>myLabel</code>, the condition would be false.
 
===Array Indexing===
The easiest way to fix this is to put a <code>NOP</code> (which does nothing) after every branch.
Arrays are declared with the total number of elements in an array.
<syntaxhighlight lang="C">int foo[4] = {4,8,12,16};</syntaxhighlight>
 
However, arrays are zero-indexed, so in your code you'll never actually want to read from/write to the same subscript used when declaring the array. Doing so indexes the array out of bounds, reading from or writing to the address of whatever happens to be stored in memory after it.
On earlier versions of MIPS, this also happened when loading from memory. The register you loaded into wouldn't have the new value during the instruction after the load. This "load delay slot" doesn't exist on MIPS III (which the Nintendo 64 uses) but it does exist on the PlayStation 1.
 
Chances are this will compile even though it's not something you really want to have happen.
<syntaxhighlight lang="mips">la $a0,0xDEADBEEF
<syntaxhighlight lang="C">int foo[4] = {4,8,12,16};
lw $t0,($a0) ;load the 32-bit value at memory address 0xDEADBEEF
int x = foo[0]; //x = 4
addiu $t0,5 ;5 is actually added BEFORE the register has gotten its new value from the memory load above. It will be clobbered.</syntaxhighlight>
int y = foo[3]; //y = 16
int z = foo[4]; //z = ?????????</syntaxhighlight>
 
===The sizeof operator===
Like with branches, putting a <code>NOP</code> after a load will solve this problem.
One of the most common misunderstandings about C arrays is the <code>sizeof</code> operator.
<syntaxhighlight lang="C">int foo()
{
char bar[20];
return sizeof(bar);
}</syntaxhighlight>
 
The gotcha is that <code>sizeof</code> can't be used to calculate anything at runtime. The <code>sizeof</code> operator merely provides a compile-time constant using the information you provided to the compiler about that variable. For arrays, the data type of the array and the number of elements are multiplied together to give the size. C uses this information to know how many bytes to reserve on the stack for the array, but the size isn't stored anywhere with the array. As far as the CPU knows, the fact that the above function's return value is the size of the array is merely a coincidence.
 
 
Put another way, <code>sizeof</code> is just a <code>#define</code> that doesn't pollute your namespace:
<syntaxhighlight lang="C">int foo()
{
#define size_of_bar 20 //the sizeof operator is the same as doing this essentially.
 
char bar[size_of_bar];
return size_of_bar;
}</syntaxhighlight>
 
As a result of this subtle nuance, many new C programmers will write the code below thinking that it will return a value corresponding to the number of elements the array was originally declared with.
<syntaxhighlight lang="C">int gotcha(char bar[])
{
return sizeof(bar);
}</syntaxhighlight>
 
This is not the case, as when passing an array to a function, you're actually passing <i> a pointer to element 0 of that array</i>. Therefore, any size information about that array is lost. In <code>main</code> we might write
<syntaxhighlight lang="C">myArray[40];
int x = gotcha(myArray);</syntaxhighlight>
 
which is actually the same as
<syntaxhighlight lang="C">myArray[40];
int x = gotcha(&myArray[0]);</syntaxhighlight>
 
As using <code>sizeof</code> on a memory address returns the number of bytes that the CPU's instruction pointer register can hold, you'll get the same return value from <code>gotcha</code> regardless of how many elements the array has. When C programmers talk about "arrays decaying into pointers" this is what they're referring to.
 
In order for a function to use an array's intended size, it must be passed in as a separate argument.
<syntaxhighlight lang="C">int foo(char buf[],int length){}
 
int main()
{
char myArray[30];
int j = foo(myArray,sizeof(myArray)); //passes 30 as the length parameter.
}</syntaxhighlight>
 
===gets()===
Computer science teachers (and even most compilers) will tell you to never use <code>gets()</code>. This function takes a pointer as an argument, and will take user input and store it at that memory address. What makes this function infamous and unsafe, however, relates to the above section. <code>gets()</code> only takes a pointer to a <code>char</code> array as an argument, and doesn't have any information about the size of the array it's writing to. The function continues to copy the user's input until the user has finished (i.e. until the Enter key is pressed). Since the user can type without limit, and the function doesn't know the size of the array, any input in excess of the array's size will overwrite whatever is in memory after the array. Since the default behavior of C is to allocate memory on the hardware stack, this can lead to overwriting a function's return address, known as a buffer overflow exploit, allowing a hacker to use <code>gets()</code> as a means to call any function in the program provided the hacker knows the function's address and the endianness of the CPU architecture.
 
===printf()===
The first function every C programmer learns (besides <code>main</code>), <code>printf</code> can be exploited in a similar fashion as <code>gets()</code>, but only if the programmer is irresponsible. <code>printf</code> can theoretically take any number of arguments; however there is no CPU that can actually support variadic functions in hardware (in the sense that the CPU knows how many arguments are passed into it without cheating, e.g. using a variable that holds the number of arguments as in <code>int argc, char** argv[]</code>).
 
The ability for <code>printf()</code> to take any number of arguments was pulled off with a dirty trick: the format string. Every time a <code>%</code> is encountered in the format string, <code>printf()</code> will accomplish the substitution using the next function argument, which depending on the calling convention starts off using registers and then pulls the rest from the stack. This isn't a problem as long as you <i><b>never let the user write the format string.</b></i> If the format string has more unescaped <code>"%"</code>s than there are arguments, <code>printf()</code> will read from the stack and assume whatever is there are the "missing" arguments. This lets a malicious user see the program's function call history which can be useful in figuring out other ways of exploiting the program.
 
<syntaxhighlight lang="C">int main()
{
int x = 3;
int y = 5;
int z = 7;
printf("%d %d %d %x %x",x,y,z); //on an Intel cpu the first %x reveals %%ebp and the second reveals the return address.)
}</syntaxhighlight>
 
=={{Header|Insitux}}==
 
A common "gotcha" in Insitux concerns one of its greatest strengths: ''any'' built-in operations under-loaded by exactly one parameter become closures. Under-loading by accidental omission is a common mistake, sometimes purely typological. Below is an example of accidental under-loading due to misuse of <code>max</code>.
 
<syntaxhighlight lang="insitux">
(let numbers [1 2 3 4]
maximum (max numbers)) ;should be (... max numbers)
(+ maximum 5)
</syntaxhighlight>
 
{{out}}
 
<pre>
3:2 (+ maximum 5)
Type Error: fast+ takes numeric arguments only, not closure.
In entry.ix
</pre>
 
This leads onto another "gotcha": Insitux substitutes any obvious instances of arithmetic operations used with two parameters with a faster alternative which, internally, does not need to iterate over ''N'' parameters. The reason this is a gotcha is two-fold: it can be a bit confusing to see e.g. <code>fast+</code> when you used <code>+</code>, and it complicates [https://www.rosettacode.org/wiki/Test_a_function#Insitux mocking] arithmetic operations.
 
<syntaxhighlight lang="insitux">
(mock + (fn a b ((unmocked +) a b 1)))
(+ 2 3)
</syntaxhighlight>
 
{{out}}
 
<pre>
5
</pre>
 
The example above "should" have returned <code>6</code>, but to achieve this we would need to mock <code>fast+</code> instead.
 
=={{header|J}}==
Line 207 ⟶ 302:
5 7 9</syntaxhighlight>
 
Here, we are adding totwo lists and then (after the first sentence) summing the result. But as you can see in the last sentence, summing the individual numbers by themselves doesn't accomplish anything useful.
 
J also has gotchas with its token formation and syntax rules.
 
# The character '.' is also "token forming" in non-numeric words and tokens. Here, ':' also follows this rule. (In both cases, this was to allow the language to use strict ascii while representing characters which were originally conceived of as having an [[wikipedia:accent|accent]] or [[wikipedia:diacrit|diacrit]]. Though, once the word forming rule was established it was applied in ways where that original analogy was no longer relevant.)
# a sequence of numbers separated by spaces is a single token, in many languages, spaces are allowed in quoted strings, but J's numbers are not quoted.
# While most people are familiar with the character 'e' being used in numbers, J's token forming rules allow any letter to be used in numbers (even when the result is not a legal number -- also 'x' has a different significance than in C).
# J uses a different character to represent negative numbers than it uses for subtraction.
# J does not have precedence rules distinguishing between <code>+</code> and <code>*</code>. All such verbs have the same precedence and are processed strictly right to left (same as assignment statements and arabic numerals).
# Also, (like many languages) J uses index origin 0 and there are some people who think in terms of index origin 1.
 
Here's a example of the token forming gotcha:
<syntaxhighlight lang=J> 10 100 1000 +/ .*1 2 3 NB. vector multiplication
3210
10 100 1000 +/.*1 2 3 NB. complex conjugate of signum of right argument grouped by the left argument
1
1
1</syntaxhighlight>
 
Here's an example of using spaces in numbers, and how it can mess with people:
<syntaxhighlight lang=J>
A=: 2 3 5 7 11 NB. legal
B=: 999 NB. legal
B 0} A NB. functional array update (does not change A)
NB. the use of a single brace to denote indexing might also confuse people
999 3 5 7 11
0} A NB. legal
2
999 0} A NB. not legal
|rank error
(999)0} A NB. what was intended
999 3 5 7 11</syntaxhighlight>
 
Here's a few other examples of how J's [[j:Vocabulary/Constants|constant notation]] can mess with people:
<syntaxhighlight lang=J>
0x100 NB. 0*e^100 where e is the natural logarithm base 2.71828...
0
0xff
|ill-formed number
16b100 16bff
256 255
8ad90 NB. 8 on the complex plane at an angle of 90 degrees from the real axis
0j8
-100 NB. two tokens
_100
_100+10 NB. three tokens
_90
-100+10 NB. four tokens
_110</syntaxhighlight>
 
The precedence and right-to-left approach give J a syntactic simplicity similar to LISP or Forth (even simpler than some implementations of those languages) while remaining an [[wikipedia:Infix|infix]] language. However, this can be confusing for people who have trained themselves on languages with more complex syntax:
 
<syntaxhighlight lang=J>
1+2*3 NB. processed right-to-left
7
2*3+1 NB. processed right-to-left
8</syntaxhighlight>
 
Finally, J is very expressive (in the formal sense), which has the effect that many
meaningless sentences are legal, so you do get less immediate feedback on your
mistakes.
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
public final class Gotchas {
 
public static void main(String[] aArgs) {
// Gotcha 1: An integer argument to a Collection, such as a List, sets the capacity of the Collection,
// but does not fill the Collection with elements.
List<Integer> numbers = new ArrayList<Integer>(100);
// The above list has the capacity to hold 100 elements, but is currently empty.
// Setting the element with index 3 to a value of 42 will create a runtime exception,
// because the list has length 0, and this element does not yet exist.
numbers.set(3, 42);
// The gotcha is only revealed when a runtime exception is thrown.
System.out.println(numbers);
// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 0
// Gotcha 2: Copying a Collection in a simple manner works,
// but means that changes to the original Collection are reflected in the copy,
// which is not normally the desired outcome.
Set<String> letters = new HashSet<String>();
letters.add("a"); letters.add("b"); letters.add("c");
// Create a copy of the set.
Set<String> copy = letters;
// The two sets are identical.
System.out.println(letters + " :: " + copy);
// Add an element to the set 'letters'.
letters.add("d");
// The same letter has been added to the set 'copy'.
// Both sets now contain the same 4 letters.
System.out.println(letters + " :: " + copy);
// In a program this can cause mysterious results which can be difficult to debug.
// The correct way to copy a Collection is to use a copy constructor as shown below.
Set<String> correctCopy = new HashSet<String>(letters);
letters.add("e");
// The set 'correctCopy' only contains its original 4 letters.
System.out.println(letters + " :: " + correctCopy);
}
 
}
</syntaxhighlight>
 
=={{header|jq}}==
Line 219 ⟶ 424:
 
One way to avoid falling into the trap in the first place is to spend some time understanding how the invocation `f(1,2)` might NOT be equivalent to `f(1),f(2)`. (Hint: `def(s): reduce s as $x (0; .+1);`)
 
=={{header|Javascript}}==
===Equality Comparisons===
The normal equality operator (<code>==</code>) is very infamous for its strange results when comparing two variables of different types. Javascript has a complicated set of type coercion rules, which was intended to simplify comparisons between integers and floating point, integers and their string representations (e.g. 2 == '2'), etc. However, this is often frustrating for the programmer when they want to know if two variables are equal and also have the same data type. The strict equality (<code>===</code>) operator will always return false if the variables are of two different types. Many new programmers are taught to always use <code>===</code> to avoid subtle bugs in their programs.
 
=={{header|Julia}}==
Line 292 ⟶ 501:
end
</pre>
 
=={{header|MIPS Assembly}}==
===Delay Slots===
Due to the way MIPS's instruction pipeline works, an instruction placed after a branch instruction is executed during the branch, ''even if the branch is taken.''
 
<syntaxhighlight lang="mips">move $t0,$zero ;load 0 into $t0
beqz $t0,myLabel ;branch if $t0 equals 0
addiu $t0,1 ;add 1 to $t0. This happens during the branch, even though the program counter never reaches this instruction.</syntaxhighlight>
 
Now, you may think that the 1 gets added first and therefore the branch doesn't take place since the conditions are no longer true. However, this is '''not the case.''' The condition is already "locked in" by the time <code>addiu $t0,1</code> finishes. If you compared again immediately upon arriving at <code>myLabel</code>, the condition would be false.
 
The easiest way to fix this is to put a <code>NOP</code> (which does nothing) after every branch.
 
On earlier versions of MIPS, this also happened when loading from memory. The register you loaded into wouldn't have the new value during the instruction after the load. This "load delay slot" doesn't exist on MIPS III (which the Nintendo 64 uses) but it does exist on the PlayStation 1.
 
<syntaxhighlight lang="mips">la $a0,0xDEADBEEF
lw $t0,($a0) ;load the 32-bit value at memory address 0xDEADBEEF
addiu $t0,5 ;5 is actually added BEFORE the register has gotten its new value from the memory load above. It will be clobbered.</syntaxhighlight>
 
Like with branches, putting a <code>NOP</code> after a load will solve this problem.
 
=={{header|Perl}}==
Line 368 ⟶ 597:
<small> (It surprises me to read Andrew Koenig in ctraps.pdf saying
"In most languages, an array with n elements normally has subscripts ranging from 1 to n inclusive.")</small>
 
=={{header|Quackery}}==
 
My two most frequent whoopsies are using <code>if</code> instead of <code>iff</code>, and forgetting to put <code>again</code> at the end of a <code>while</code> loop. Both are hard to guard against as pretty much any sequence of words could be a reasonable construct in Quackery.
 
One gotcha specific to programmers with experience of Forth could be that the outputs of <code>/mod</code> are the opposite way round in Quackery.
 
=={{header|Raku}}==
Line 519 ⟶ 754:
 
I've tried to construct an example below which illustrates these pitfalls.
<syntaxhighlight lang="ecmascriptwren">class Rectangle {
construct new(width, height) {
// Create two fields.
9,476

edits