copy else statement to if statement - reverse

I am trying to copy the code of else state to the if statement.
In here I see if-eqz as the if condition but I don't know where the else condition is here. Can someone help me find else condition so that I can copy it to become the if code also.
I also want to know where is the start and the end of the else statement body
if-eqz v1, :cond_1
.line 103
:goto_1
return-object v0
.line 82
:cond_0
invoke-static {}, Landroid/os/Environment;->getExternalStorageDirectory()Ljava/io/File;
move-result-object v0
invoke-virtual {v0}, Ljava/io/File;->getAbsolutePath()Ljava/lang/String;
move-result-object v0
.line 83
new-instance v2, Ljava/lang/StringBuilder;
invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v2, "/Android/data/"
invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
sget-object v2, Lcom/lingren/game/MonoJavaHelper;->s_Application:Landroid/app/Application;
invoke-virtual {v2}, Landroid/app/Application;->getPackageName()Ljava/lang/String;
move-result-object v2
invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v2, "/files/Res/AssistObj/"
invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
.line 84
const-string v2, "MonoJavaHelper"
new-instance v3, Ljava/lang/StringBuilder;
invoke-direct {v3}, Ljava/lang/StringBuilder;-><init>()V
const-string v4, "ExternalStorageState Not UseAble:"
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
invoke-virtual {v3, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v1
invoke-static {v2, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
goto :goto_0
.line 95
:cond_1
:try_start_1
invoke-virtual {p0}, Landroid/app/Activity;->getApplicationContext()Landroid/content/Context;
move-result-object v1
invoke-virtual {v1}, Landroid/content/Context;->getFilesDir()Ljava/io/File;
move-result-object v1
invoke-virtual {v1}, Ljava/io/File;->getAbsolutePath()Ljava/lang/String;
move-result-object v0
.line 96
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
const-string v2, "/Res/AssistObj/"
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
:try_end_1
.catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_0
move-result-object v0
goto :goto_1

Your example seems incomplete. For example it has goto :goto_0 but doesn't contain the :goto_0 label. In any event, the following example should help you to figure out how to handle your case. Smali code like the following:
if-nez v0, :cond_0
const-string v2, "hello 1"
:goto_0
return-void
:cond_0
const-string v2, "hello 2"
goto :goto_0
Corresponds to Java code like:
if (i == 0) {
s = "hello 1";
}
else {
s = "hello 2";
}
return;
The exact placement of goto statements and branches depends on compiler. Also for different conditions you may see if-nez or if-eqz or some other statements.

Related

Pytorch autograd function backward is doesn't work ( which is output 0 of MmBackward, is at version 1; expected version 0 instead)

I'm making a model mixing Fine-tuning CLIP model & Freezing clip model. And I make a custom loss using kl_loss and CEE
with torch.no_grad():
zero_shot_image_features = zero_shot_model.encode_image(input_image)
zero_shot_context_text_features = zero_shot_model.encode_text(context_label_text)
zero_shot_image_features /= zero_shot_image_features.norm(dim=-1, keepdim=True)
zero_shot_context_text_features /= zero_shot_context_text_features.norm(dim=-1, keepdim=True)
zero_shot_output_context = (zero_shot_image_features # zero_shot_context_text_features.T).softmax(dim=-1)
fine_tunning_image_features = fine_tunning_model.encode_image(input_image)
fine_tunning_context_text_features = fine_tunning_model.encode_text(context_label_text)
fine_tunning_image_features /= fine_tunning_image_features.norm(dim=-1, keepdim=True)
fine_tunning_context_text_features /= fine_tunning_context_text_features.norm(dim=-1, keepdim=True)
fine_tunning_output_context = (fine_tunning_image_features # fine_tunning_context_text_features.T).softmax(dim=-1)
fine_tunning_label_text_features = fine_tunning_model.encode_text(label_text)
fine_tunning_label_text_features /= fine_tunning_label_text_features.norm(dim=-1, keepdim=True)
fine_tunning_output_label = (fine_tunning_image_features # fine_tunning_label_text_features.T).softmax(dim=-1)
optimizer_zeroshot.zero_grad()
optimizer_finetunning.zero_grad()
loss.backward(retain_graph=True)
def custom_loss(zero_shot_output_context, fine_output_context, fine_output_label, target, alpha):
\# Compute the cross entropy loss
ce_loss = F.cross_entropy(fine_output_label, target)
# Compute ce_loss KL divergence between the output and the target
kl_loss = F.kl_div(zero_shot_output_context.log(), fine_output_context.log(), reduction = 'batchmean').requires_grad_(True)
final_loss = (ce_loss + alpha * kl_loss)
return final_loss
RuntimeError Traceback (most recent call last) Cell In[18], line 81 78 optimizer2.zero_grad() 79 optimizer.zero_grad() ---> 81 loss.backward(retain_graph=True) 83 if device == "cpu": 84 optimizer.step()
File ~/anaconda3/envs/sh_clip/lib/python3.8/site-packages/torch/tensor.py:221, in Tensor.backward(self, gradient, retain_graph, create_graph) 213 if type(self) is not Tensor and has_torch_function(relevant_args): 214 return handle_torch_function( 215 Tensor.backward, 216 relevant_args, (...) 219 retain_graph=retain_graph, 220 create_graph=create_graph) --> 221 torch.autograd.backward(self, gradient, retain_graph, create_graph)
File ~/anaconda3/envs/sh_clip/lib/python3.8/site-packages/torch/autograd/init.py:130, in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables) 127 if retain_graph is None: 128 retain_graph = create_graph --> 130 Variable.execution_engine.run_backward( 131 tensors, grad_tensors, retain_graph, create_graph, 132 allow_unreachable=True)
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.HalfTensor [6, 1024]], which is output 0 of MmBackward, is at version 1; expected version 0 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
But when I have train model, backward() function dosen't work,,,,, how to fix it??
You use 'a /= b' which is an inplace operation, it will work well if you change it to 'a = a/b'.

MIPS assembly understanding READ syscall

I have a piece of code in MIPS I am failing to understand. Namely the register convention using the "read" linux syscall:
...
move a0,zero #a0 = 0
move a1,s0 #a1 = some adress in memory
li v0,4003 #v0 = 4003 = SYSCALL READ
syscall
bnez a3, label #What is in a3??
li v1,1
bne v0,v1
...
Now I get understand it as
char buffer;
int v0 = read(0, &buffer, 1);
????
What I do not get at all is what is the meaning of reg a3 in this context? v0 is the return value of read, but a3 should be parameter and not ret value. Is it errno?
It's a boolean indicating whether or not there was an error:
On a few architectures, a register is used as a boolean (0
indicating no error, and -1 indicating an error) to signal
that the system call failed.
Arch/ABI Instruction System Ret Ret Error
call # val val2
-------------------------------------------------------------
mips syscall v0 v0 v1 a3
source

How do I get result of invoke direct?

I am trying to understand what is happening in the following smali code:
I am trying to log the result or stored value in key:
# creates new instance of SecretKeySpec in register v8
new-instance v8, Ljavax/crypto/spec/SecretKeySpec;
# store contant 0x0 in v0
const/4 v0, 0x0
aget-object v0, v9, v0
# store string AES in v1
const-string v1, "AES"
# calls new SecretKeySpec(v0,v1);
invoke-direct {v8, v0, v1}, Ljavax/crypto/spec/SecretKeySpec;-><init>([BLjava/lang/String;)V
.line 115
.local v8, "key":Ljavax/crypto/spec/SecretKeySpec;
The invoke-direct call there is calling the constructor. Object creation in Java (and Dalvik) bytecode takes two instructions. The first, new-instance allocates an uninitialized object, while invoke-direct calls the constructor to initialize this object. The object is stored in v8, as you can see from the new-instance instruction.

Chrome getting crashed with my simple GWT Application

I have written a simple gwt application, and when i am using it in chrome browser, it is getting crashed.
So i debug chrome using windbg tool to take dump. And here is my dump..
(cc0.15d8): Break instruction exception - code 80000003 (first chance)
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\Google\Chrome\Application\33.0.1750.154\chrome_child.dll -
eax=00000068 ebx=00000000 ecx=6dc299a6 edx=0b73a067 esi=0044d770 edi=01a6d000
eip=6daf00d3 esp=0044d750 ebp=0044d750 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
chrome_child!ovly_debug_event+0xb4d33f:
6daf00d3 cc int 3
7:044> g
#
# Fatal error in , line 0
# API fatal error handler returned after process out of memory
#
(cc0.15d8): Break instruction exception - code 80000003 (first chance)
eax=00000001 ebx=00000000 ecx=6d212db0 edx=ff61f000 esi=6e67b598 edi=0044d754
eip=6d51ff03 esp=0044d734 ebp=0044d740 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
chrome_child!ovly_debug_event+0x57d16f:
6d51ff03 cc int 3
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (!!! second chance !!!)
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
7:044> g
(cc0.15d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2ea08261 ebx=00000044 ecx=00000004 edx=01a6d000 esi=0044ded8 edi=00000010
eip=6cffd8db esp=0044dde0 ebp=0044de08 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
chrome_child!ovly_debug_event+0x5ab47:
6cffd8db 8903 mov dword ptr [ebx],eax ds:002b:00000044=????????
Please correct me if i am going wrong to find solution.
Any help would be appreciated.
Thanks, PK
First of all, you should load the right symbols of program,otherwise you cannot figure out in which function the exception occurs.For example : if you load the right symbol in windbg,the windbg will tell you the exception occurs in the function FOO()+0x12,otherwise it will tell that you should check the position MAIN()+0x1234 which also point to FOO()+0x12 but have less meaning to human being.
so the first step to take is loading the right debug symbols.

What is spaghetti code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Can you post a short example of real, overdone spaghetti code, possibly saying what it does? Can you show me a little debugger's nightmare?
I don't mean IOCCC code, that is science fiction. I mean real life examples that happened to you...
Update
The focus has changed from "post some spaghetti code" to "what is exactly spaghetti code?". From a historical perspective, the current choices seem to be:
old Fortran code using computed gotos massively
old Cobol code using the ALTER statement
To me, a more modern example of spaghetti code is when you have 20 dlls and every DLL references each other in one way or another. Your dependency graph looks like a huge blob, and your code hops all over the place with no real order. Everything is inter-dependent.
I'm not pulling this out of my head. This is what I have had to work with, albeit simplified. Let's say that basically you have a program that needs an enum:
enum {
a, b, c;
} myenum;
But instead what we have is
HashTable t;
t["a"] = 0;
t["b"] = 1;
t["c"] = 2;
But of course, no implementation of a hash table is good enough so there is a local implementation of hash tables, which contains about 10 times more code than an average open source implementation with half the features and double the number of bugs. The HashTable is actually defined virtual, and there's a factory HashTableFactory to create instances of HashTables, but true to the pattern HashTableFactory is also virtual. To prevent an infite cascade of virtual classes there's a function
HashTableFactory *makeHashTableFactor();
Thus everywhere where the code needs myenum's it carries a reference to the instance of a HashTable and HashTableFactory, in case you want to make more HashTable's. But wait, that's not all! This is not how the hash table is initialized, but it's done by writing a code that reads XML:
<enum>
<item name="a" value="0"/>
<item name="b" value="1"/>
<item name="c" value="2"/>
</enum>
and inserts into a hash table. But the code is "optimised" so that it doesn't read an ascii file myenum.xml, but instead there's a compile time script which generates:
const char* myenumXML = [13, 32, 53 ....];
from myenum.xml and the hash table is initialized by a function:
void xmlToHashTable(char *xml, HashTable *h, HashTableFactory *f);
which is called:
HashTableFactory *factory = makeHashTableFactory();
HashTable *t = facotry.make();
xmlToHashTable(myenumXML, t, f);
Ok, so we have a lot of code to get an enum structure. It's basically used in a function:
void printStuff(int c) {
switch (c) {
case a: print("a");
case b: print("b");
case c: print("c");
}
}
and this is called in a context where:
void stuff(char* str) {
int c = charToEnum(str);
printStuff(c);
}
So what we actually have is instead of
void stuff(char *str) {
printf(str);
}
we have manged to generate thousands of lines of code (private new, buggy, complex, implementation of hashtables, and xml readers, and writer) in place of the above 3.
There's also Ravioli Code, which is the opposite. Nice little chunks of functionality, a clean interface neatly wrapped around meaty goodness, all sat in a nice sauce of framework.
From a Linux SCSI driver (which shall remain nameless to protect the guilty):
wait_nomsg:
if ((inb(tmport) & 0x04) != 0) {
goto wait_nomsg;
}
outb(1, 0x80);
udelay(100);
for (n = 0; n < 0x30000; n++) {
if ((inb(tmport) & 0x80) != 0) { /* bsy ? */
goto wait_io;
}
}
goto TCM_SYNC;
wait_io:
for (n = 0; n < 0x30000; n++) {
if ((inb(tmport) & 0x81) == 0x0081) {
goto wait_io1;
}
}
goto TCM_SYNC;
wait_io1:
inb(0x80);
val |= 0x8003; /* io,cd,db7 */
outw(val, tmport);
inb(0x80);
val &= 0x00bf; /* no sel */
outw(val, tmport);
outb(2, 0x80);
TCM_SYNC:
/* ... */
small_id:
m = 1;
m <<= k;
if ((m & assignid_map) == 0) {
goto G2Q_QUIN;
}
if (k > 0) {
k--;
goto small_id;
}
G2Q5: /* srch from max acceptable ID# */
k = i; /* max acceptable ID# */
G2Q_LP:
m = 1;
m <<= k;
if ((m & assignid_map) == 0) {
goto G2Q_QUIN;
}
if (k > 0) {
k--;
goto G2Q_LP;
}
G2Q_QUIN: /* k=binID#, */
How did I locate this gem?
find /usr/src/linux -type f -name \*.c |
while read f
do
echo -n "$f "
sed -n 's/^.*goto *\([^;]*\);.*/\1/p' $f | sort -u | wc -l
done |
sort +1rn |
head
The output is a series of lines listing files ordered by the number of gotos to distinct labels, like the following:
kernel/fork.c 31
fs/namei.c 35
drivers/infiniband/hw/mthca/mthca_main.c 36
fs/cifs/cifssmb.c 45
fs/ntfs/super.c 47
Don't forget to mention Object-oriented spaghetti.
This is when you try to use all the design patterns in the book, even when they don't make sense. This leads to spaghetti code at conceptual level, which is far more detrimental to quality than classical goto-based spaghetti code.
Real spaghetti code was done in COBOL and used the ALTER statement.
Here's an example, while listed a "humor", I've seen this kind of thing. Almost got fired once for noting that any program with an Alter statement was obviously in a state of sin. I refused to "maintain" that program, it was quicker to replace it than understand it.
You've asked for it, you'll get it:
This is the source of a DOS .com file that plays the Blue Danube waltz. The executable is just 176 bytes in size. Code is re-used as data and vice versa.
.286
.model tiny
g4 equ 55-48 ; removed note-decoding !
a4 equ 57-48 ; now: storing midi-notes for octaves 0..2 and convert
h4 equ 59-48 ; to 4..6 with a simple add 48.
c5 equ 60-48
d5 equ 62-48
e5 equ 64-48
g5 equ 67-48
h5 equ 71-48
c6 equ 72-48
d6 equ 74-48
e6 equ 76-48
g6 equ 79-48 ; = 00011111b
pp equ 0 ; c4 is not used in the walz, using it as play-pause.
EOM equ 1 ; c#4 is also available... End Of Music
; warning: experts only beyond this point !
pau1 equ 00100000b ; bitfield definitions for note-compression
pau2 equ 01000000b ; you can or a pau to each note!
pau3 equ 01100000b
;rep1 equ 01000000b ; rep1 is history (only used once).
;rep3 equ 11000000b ; rep3 was never used.
rep2 equ 10000000b ; or a rep2 to a note to play it 3 times.
drumsize equ 5
.code
org 100h
start:
mov ah,9
mov dx,offset msg
int 21h ; print our headerstring
mov dx,0330h ; gus midi megaem -port
mov si,offset music_code ; start of music data
mainloop:
; get new note (melody)
xor bp,bp ; bp= repeat-counter
lodsb ; get a new note
cmp al, EOM ; check for end
jne continue
ret
continue:
jns no_rep2 ; check for rep2-Bit
inc bp
inc bp ; "build" repeat-counter
no_rep2:
push ax ; save the note for pause
; "convert" to midi-note
and al,00011111b
jz skip_pp ; check pp, keep it 0
add al,48 ; fix-up oktave
skip_pp:
xchg ax,bx ; bl= midi-note
play_again:
mov cl,3
push cx ; patch program (3= piano)
push 0c8h ; program change, channel 9
; wait (cx:dx) times
mov ah,86h ; wait a little bit
int 15h
; prepare drums
dec di ; get the current drum
jns no_drum_underflow
mov di,drumsize
no_drum_underflow:
; play drum
push dx ; volume drum
push [word ptr drumtrk+di] ; note drum
mov al,99h
push ax ; play channel 10
; play melody
push dx ; volume melody
push bx ; note melody
dec ax ; replaces dec al :)
push ax ; play channel 9
; send data to midi-port
mov cl,8 ; we have to send 8 bytes
play_loop:
pop ax ; get the midi event
out dx,al ; and send it
loop play_loop
; repeat "bp" times
dec bp ; repeat the note
jns play_again
; check and "play" pause
xor bx,bx ; clear the note, so we can hear
; a pause
; decode pause value
pop ax
test al,01100000b
jz mainloop ; no pause, get next note
; decrement pause value and save on stack
sub al,20h
push ax
jmp play_again ; and play next drum
; don't change the order of the following data, it is heavily crosslinked !
music_code db pp or rep2
db g4 or rep2 or pau1
db h4 or pau1, d5 or pau1, d5 or pau3
db d6 or pau1, d6 or pau3, h5 or pau1, h5 or pau3
db g4 or rep2 or pau1
db h4 or pau1, d5 or pau1, d5 or pau3
db d6 or pau1, d6 or pau3, c6 or pau1, c6 or pau3
db a4 or rep2 or pau1
db c5 or pau1, e5 or pau1, e5 or pau3
db e6 or pau1, e6 or pau3, c6 or pau1, c6 or pau3
db a4 or rep2 or pau1
db c5 or pau1, e5 or pau1, e5 or pau3
db e6 or pau1, e6 or pau3, h5 or pau1, h5 or pau3
db g4 or rep2 or pau1
db h4 or pau1, g5 or pau1, g5 or pau3
db g6 or pau1, g6 or pau3, d6 or pau1, d6 or pau3
db g4 or rep2 or pau1
db h4 or pau1, g5 or pau1, g5 or pau3
db g6 or pau1, g6 or pau3, e6 or pau1, e6 or pau3
db a4 or rep2 or pau1
db c5 or pau1, e5 or pau1, e5 or pau3, pp or pau3
db c5 or pau1, e5 or pau1, h5 or pau3, pp or pau3, d5 or pau1
db h4 or pau1, h4 or pau3
db a4 or pau1, e5 or pau3
db d5 or pau1, g4 or pau2
; db g4 or rep1 or pau1
; replace this last "rep1"-note with two (equal-sounding) notes
db g4
db g4 or pau1
msg db EOM, 'Docking Station',10,'doj&sub'
drumtrk db 36, 42, 38, 42, 38, 59 ; reversed order to save some bytes !
end start
Real spaghetti-code requires a multitude of non-local gotos. Sadly this is not possible using most modern languages.
Edit: Some suggest exceptions and longjmp as substitutes for GOTO. But these are far to limited and structured, since they only allow you to return up the callstack. Real GOTO allows you to jump to any line anywhere in the program, which is necessary to create real spaghetti.
In simple terms spaghetti code is any code in any programming language in which it is not possible to trace the next post of execution, or at least difficult to determine where the next point goes in response of one action.
This is from a MIDI parser I wrote some time ago. It was a quick and dirty proof of concept, but nevertheless, I shall take the blame for its ugliness: 4 levels of nested conditionals plus the dreaded multiple returns. This code was meant to compare 2 MIDI events in order to sort them by priority when writing to a file. Ugly as it was, it did the job decently, though.
internal class EventContainerComparer : IComparer {
int IComparer.Compare(object a, object b) {
MIDIEventContainer evt1 = (MIDIEventContainer) a;
MIDIEventContainer evt2 = (MIDIEventContainer) b;
ChannelEvent chanEvt1;
ChannelEvent chanEvt2;
if (evt1.AbsoluteTime < evt2.AbsoluteTime) {
return -1;
} else if (evt1.AbsoluteTime > evt2.AbsoluteTime) {
return 1;
} else {
// a iguar valor de AbsoluteTime, los channelEvent tienen prioridad
if(evt1.MidiEvent is ChannelEvent && evt2.MidiEvent is MetaEvent) {
return -1;
} else if(evt1.MidiEvent is MetaEvent && evt2.MidiEvent is ChannelEvent){
return 1;
// si ambos son channelEvent, dar prioridad a NoteOn == 0 sobre NoteOn > 0
} else if(evt1.MidiEvent is ChannelEvent && evt2.MidiEvent is ChannelEvent) {
chanEvt1 = (ChannelEvent) evt1.MidiEvent;
chanEvt2 = (ChannelEvent) evt2.MidiEvent;
// si ambos son NoteOn
if( chanEvt1.EventType == ChannelEventType.NoteOn
&& chanEvt2.EventType == ChannelEventType.NoteOn){
// chanEvt1 en NoteOn(0) y el 2 es NoteOn(>0)
if(chanEvt1.Arg1 == 0 && chanEvt2.Arg1 > 0) {
return -1;
// chanEvt1 en NoteOn(0) y el 2 es NoteOn(>0)
} else if(chanEvt2.Arg1 == 0 && chanEvt1.Arg1 > 0) {
return 1;
} else {
return 0;
}
// son 2 ChannelEvent, pero no son los 2 NoteOn, el orden es indistinto
} else {
return 0;
}
// son 2 MetaEvent, el orden es indistinto
} else {
return 0;
}
}
}
}
Here is the Duff's Device, from Matt's answer to this question:
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
Spaghetti code: Originating in the early 60's in Italy as an alternate recipe for certain pasta dishes, spaghetti code was cooked up by one restaurant entrepreneur who attempted to automate the creation of a fool-proof entree. Pressed by the lack of time to complete the design the engineer/chef cut corners which introduced problems in the recipe early on. In a frantic attempt to remedy a good idea gone bad, various spices were quickly added to the concoction as the recipe grew out of control. The result was a stringy, twisty, yet potentially tasty pile of text that would later grow to be a practice cherished by developers world-wide.
Have you ever looked at code generated by Flex/Bison scanner and generator? A plethora of labels and preprocessor directives.
It's absolutely impossible to understand what's inside.. and absolutely impossible to follow flow of the program.
That's definetely spaghetti code.