Jump to content

Low level programming languages

Hi P
10 minutes ago, reniat said:

proper code organization. I feel like you are just ignoring the possibility that when properly written, assembly can actually be readable and attacking this strawman of badly written assembly that abuses gotos and labels.

 

And yet there are hundreds of thousands if not millions of developers who don't mind working in assembly.

I seriously don't know why you guys like to go against common wisdom and advocate gotos and labels can be a good programming styles....

 

I talk in absolutes because if something is bad  idea, then just don't do it, regardless if outcome is good or not. You can be completely fine if you rush red lights but I would talk in absolute term you shouldnt. Same goes for goto.

But whatever. I guess you just need to be open and accommodating. 

 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

4 minutes ago, wasab said:

I seriously don't know why you guys like to go against common wisdom and advocate gotos and labels can be a good programming styles....

It's important to be very clear about what we're saying. We're not saying using goto in high level languages that have better mechanisms is recommended (If I catch someone using a goto in C++ they'd better have an EXTREMELY good reason for it). We're saying that assembly isn't automatically hard to read because it uses gotos.

 

Saying "Through proper organization, you can make labels readable and effective, allowing for proper development in assembly" 

is different than saying "labels and gotos are amazing and should be used everywhere in every language".

 

Different languages can have different best practices, and that's okay, because languages have different needs and different contexts.

 

4 minutes ago, wasab said:

I talk in absolutes

 

4 minutes ago, wasab said:

I guess you just need to be open and accommodating. 

wat

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, reniat said:

It's important to be very clear about what we're saying. We're not saying using goto in high level languages that have better mechanisms is recommended (If I catch someone using a goto in C++ they'd better have an EXTREMELY good reason for it). We're saying that assembly isn't automatically hard to read because it uses gotos.

 

 

Assembly is harder to follow and to read precisely because it has no functions and variables and rely on jump, labels, and registers. Or perhaps you want to go against the general consensus and tell me assembly is easier to follow as well? 

 

5 minutes ago, reniat said:

 

wat

Talking about you not me. You want to be open to bad ideas. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

12 minutes ago, wasab said:

Or perhaps you want to go against the general consensus and tell me assembly is easier to follow as well? 

It's not EASIER than high level languages (that's literally why they exist), but it's REASONABLE. There's a very significant difference there. Of course assembly is harder to make clean, that's why you don't see large scale applications being written in pure assembly. But to say that it's impossible to write clean code in assembly is just ignorant.

 

And no, the general consensus is not to "avoid avoid avoid assembly". It's "use assembly where it makes sense to". It's really quite common to have performance critical systems written in C or C++, with pockets of assembly for highly performance critical sections.

16 minutes ago, wasab said:

Talking about you not me. You want to be open to bad ideas. 

So we need to be open, to being not open, to a critical underlying piece of our modern development technology... right.

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

42 minutes ago, wasab said:

Goto and labels are something I have issues with because they are simply all over the place. You can literally jump out of loop into a random line of code. That is just pure madness.

You're describing the behavior of literally any source code with control flow statements in it. Besides that, how is this:

def foobar():
    # Do the thing
    return

foobar()

Different from

foobar:
    ; Do the thing
    ret

call foobar

This looks similar. ?

 

33 minutes ago, wasab said:

I seriously don't know why you guys like to go against common wisdom and advocate gotos and labels can be a good programming styles....

We're not saying that using gotos and labels are good programming styles. We're arguing against your assertion that goto is always bad and we should avoid them like the plague.

 

Also am waiting for your comment about Torvald's use of gotos in C code.

 

Quote

I talk in absolutes because if something is bad  idea, then just don't do it, regardless if outcome is good or not. You can be completely fine if you rush red lights but I would talk in absolute term you shouldnt. Same goes for goto.

What's the ultimate goal of programming? To write a program. To add to that, to write a program that works.

 

If my methods produce a program that's:

  • Relatively error free
  • Reliable
  • Usable to my customer

Then I've done my job and how I get there is irrelevant to how you would've done it. If I can produce a program in assembly and maintain it with relative ease* while you're struggling to produce a program in C or some other higher level language that means none of those points, telling me that my "bad programming practices" of using gotos and labels means you're salty.

 

Here's an example of someone's project that if I were to do it, I'd do things differently. But I'm not the author, the author explained why he does things the way they do that make sense to him, and at the end of the day, he has the workings of a game that people are looking forward to:

 

The problem I have with what you're saying is you're trying to take what works for you and present as "this is how everyone should do it." Or as another professional programmer put it: "If a particular practice is followed by a group of programmers then it becomes common within that group, but it may not necessarily be best."

 

*(being the original author only provides some advantage of ease of maintenance, you're very likely to forget most of how things worked if you stopped thinking about it in a relatively short period of time)

Quote

But whatever. I guess you just need to be open and accommodating.

Says the person who refuses to believe that assembly language is nothing but terrible and constantly shoots down anyone who says otherwise.

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, reniat said:

It's not EASIER than high level languages (that's literally why they exist), but it's REASONABLE. There's a very significant difference there. Of course assembly is harder to make clean, that's why you don't see large scale applications being written in pure assembly. But to say that it's impossible to write clean code in assembly is just ignorant.

 

And no, the general consensus is not to "avoid avoid avoid assembly". It's "use assembly where it makes sense to". It's really quite common to have performance critical systems written in C or C++, with pockets of assembly for highly performance critical sections.

So we need to be open, to being not open, to a critical underlying piece of our modern development technology... right.

The worst written assembly is always going to be worse than the worst written higher languages. 

 

The best written higher languages is always going to be better written than the best written assembly. 

 

Everything in between is irrelevant as far as picking the right choice of language which are both equally capable of doing the same job is concern. 

 

Why you wish to avodcate assembly when there is much better choice just as there is much better choice of programming styles than gotos and labels? 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, wasab said:

The worst written assembly is always going to be worse than the worst written higher languages. 

Why is this even a relevant comparison? Bad code has no bottom. There are literally competitions involving writing bad code.

 

2 minutes ago, wasab said:

The best written higher languages is always going to be better written than the best written assembly. 

Better in what way? More readable sure, but that's only a piece of a bigger equation for "what language should I use". 

 

3 minutes ago, wasab said:

Everything in between is irrelevant as far as picking the right choice of language which are both equally capable of doing the same job is concern. 

So you're just ignoring cases where you are writing a small amount of logic that needs to be as fast as humanly possible? I wouldn't use java for that that's for damn sure.

 

5 minutes ago, wasab said:

Why you wish to avodcate assembly when there is much better choice just as there is much better choice of programming styles than gotos and labels? 

You seem to be under the impression that assembly is ALWAYS a worse choice, when this depends ENTIRELY on the context of the decision.

 

Making a web front end? Yea dont use assembly.

Making a desktop app? Probably better in something like Java/C/C++/C#.

Making an embedded device that has teeny tiny resources? using a combination of C/C++ and pockets of assembly is perfect.

Making a piece of software to handle critical transactions at a speed where 1ms is an eternity? Yeah not gonna let Java garbage collect there....

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

8 minutes ago, Mira Yurizaki said:

You're describing the behavior of literally any source code with control flow statements in it. Besides that, how is this:


def foobar():
    # Do the thing
    return

foobar()

Different from


foobar:
    ; Do the thing
    ret

call foobar

This looks similar. ?

 

We're not saying that using gotos and labels are good programming styles. We're arguing against your assertion that goto is always bad and we should avoid them like the plague.

 

Also am waiting for your comment about Torvald's use of gotos in C code.

 

What's the ultimate goal of programming? To write a program. To add to that, to write a program that works.

 

If my methods produce a program that's:

  • Relatively error free
  • Reliable
  • Usable to my customer

Then I've done my job and how I get there is irrelevant to how you would've done it. If I can produce a program in assembly and maintain it with relative ease* while you're struggling to produce a program in C or some other higher level language that means none of those points, telling me that my "bad programming practices" of using gotos and labels means you're salty.

 

Here's an example of someone's project that if I were to do it, I'd do things differently. But I'm not the author, the author explained why he does things the way they do that make sense to him, and at the end of the day, he has the workings of a game that people are looking forward to:

 

The problem I have with what you're saying is you're trying to take what works for you and present as "this is how everyone should do it." Or as another professional programmer put it: "If a particular practice is followed by a group of programmers then it becomes common within that group, but it may not necessarily be best."

 

*(being the original author only provides some advantage of ease of maintenance, you're very likely to forget most of how things worked if you stopped thinking about it in a relatively short period of time)

Says the person who refuses to believe that assembly language is nothing but terrible and constantly shoots down anyone who says otherwise.

I shoot down bad ideas and discourages people from trying bad ideas. What issues you have against that? 

 

Goto should be avoided like a plague. Anything else is tolerance of bad programming. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

3 minutes ago, wasab said:

I shoot down bad ideas and discourages people from trying bad ideas. What issues you have against that? 

The issue is you've defined an entire industry as a bad idea rofl

 

3 minutes ago, wasab said:

Goto should be avoided like a plague. Anything else is tolerance of bad programming. 

Trust me, i'm in the "no goto" camp, but you are going off the deep end with this. Goto is bad practice now because high level languages have better solutions to the things that goto solved. It's not that goto is by itself bad, it's that other languages grew beyond it. In assembly where you don't have those higher level solutions, you need goto, and thats COMPLETELY FINE when used properly. 

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

5 minutes ago, reniat said:

Why is this even a relevant comparison? Bad code has no bottom. There are literally competitions involving writing bad code.

If badness of a written code is infinite, assembly has a bigger infinity okay?

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, reniat said:

The issue is you've defined an entire industry as a bad idea rofl

 

Trust me, i'm in the "no goto" camp, but you are going off the deep end with this. Goto is bad practice now because high level languages have better solutions to the things that goto solved. It's not that goto is by itself bad, it's that other languages grew beyond it. In assembly where you don't have those higher level solutions, you need goto, and thats COMPLETELY FINE when used properly. 

And programming has grown beyond just assembly and machine code. I would AVOID assembly like a plague when there are better choices. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, wasab said:

when there are better choices. 

It's fine to not like assembly, and I would agree that it's correct to not use assembly where it doesn't make sense. But you've been attacking the language itself instead and insisting it's worse in every aspect this entire thread. Whether it was intentional or not, you certainly have not come across as "assembly is the right tool sometimes" throughout this thread.

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, reniat said:

It's fine to not like assembly, and I would agree that it's correct to not use assembly where it doesn't make sense. But you've been attacking the language itself instead and insisting it's worse in every aspect this entire thread. Whether it was intentional or not, you certainly have not come across as "assembly is the right tool sometimes" throughout this thread.

I'm attacking assembly as a readable language not it's usefulness. I tell you to not use assembly because the code is spaghetti style, not it's capability. My original post is avoid avoid avoid avoid because code reads like a spaghetti. 

 

 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, wasab said:

My original post is avoid avoid avoid avoid because code reads like a spaghetti. 

And we gave you a bunch of ways of avoiding spaghetti code when working assembly, and you dismissed them simply because of the existence of goto without thinking about WHY goto is a bad practice and how you might avoid those pitfalls in an environment where goto is your only option.

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, reniat said:

And we gave you a bunch of ways of avoiding spaghetti code when working assembly, and you dismissed them simply because of the existence of goto without thinking about WHY goto is a bad practice and how you might avoid those pitfalls in an environment where goto is your only option.

The best way to avoid go to spaghetti in assembly is not to use assembly at all.

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

6 minutes ago, wasab said:

The best way to avoid go to spaghetti in assembly is not to use assembly at all.

Or just learn how to write it properly, if the problem calls for assembly. The worst thing you can be in this industry is stubborn.

 

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

4 minutes ago, reniat said:

Or just learn how to write it properly, if the problem calls for assembly. The worst thing you can be in this industry is stubborn.

 

I'm pretty sure there are gazillion ways to avoid writing assembly. Just pick one. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

6 minutes ago, reniat said:

Or just learn how to write it properly, if the problem calls for assembly.

One would imagine writing a few macro's that provide loop and branch logic and the main code need not ever have a single goto in it :)

Link to comment
Share on other sites

Link to post
Share on other sites

12 minutes ago, wasab said:

I'm pretty sure there are gazillion ways to avoid writing assembly. Just pick one. 

If you're recommending finding other ways to avoid writing in assembly "when the problem calls for assembly", then I hope you realize how silly that sounds.

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

9 minutes ago, reniat said:

If you're recommending finding other ways to avoid writing in assembly "when the problem calls for assembly", then I hope you realize how silly that sounds.

It's siller if you do not try your utmost to avoid both gotos and assembly when coding your application. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

7 minutes ago, wasab said:

It's siller if you do not try your utmost to avoid both gotos and assembly when coding your application. 

If assembly is the best fit for a problem, and you do extra work to try and force another solution that doesn't use assembly simply because you dislike it, i'd argue that is just bad engineering.

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, wasab said:

I shoot down bad ideas and discourages people from trying bad ideas. What issues you have against that? 

The issue is your seemingly knee-jerk reaction that seeing said "bad idea" should be shot down with a Death Star laser without considering why anyone would use it in the first place.

 

Quote

Goto should be avoided like a plague. Anything else is tolerance of bad programming. 

Okay. Let me provide you an example where goto would actually be useful.

 

void foobar(){
  char * something_1 = malloc(SOME_SIZE);
  char * something_2 = malloc(SOME_SIZE);
  char * something_3 = malloc(SOME_SIZE);

  if (do_step_1(something_1) == BAD_RESULT){
    return;
  }
  
  if (do_step_2(something_2) == BAD_RESULT){
    return;
  }
  
  if (do_step_3(something_3) == BAD_RESULT){
    return;
  }
  
  do_all_the_things(something_1, something_2, something_3);
  
  free(something_1);
  free(something_2);
  free(something_3);
}

There's a problem with this code: it can leak memory if any one of the three "do_something" returns a bad result because the function returns early without cleaning it up. So you might go "well that's easy to fix" and do this:

 

void foobar(){
  char * something_1 = NULL;
  char * something_2 = NULL;
  char * something_3 = NULL;

  something_1 = malloc(SOME_SIZE);
  if (do_step_1(something_1) == BAD_RESULT){
    free(something_1);
    return;
  }
  
  something_2 = malloc(SOME_SIZE);
  if (do_step_2(something_2) == BAD_RESULT){
    free(something_1);
    free(something_2);
    return;
  }
  
  something_3 = malloc(SOME_SIZE);
  if (do_step_3(something_3) == BAD_RESULT){
    free(something_1);
    free(something_2);
    free(something_3);
    return;
  }
  
  do_all_the_things(something_1, something_2, something_3);
  
  free(something_1);
  free(something_2);
  free(something_3);
}

Well... this is starting to look ugly. And what if we wanted to add a something_4 or something_5 to do some processing after do_all_the_things? Now you have to do this:

void foobar(){
  char * something_1 = NULL;
  char * something_2 = NULL;
  char * something_3 = NULL;
  char * something_4 = NULL;
  char * something_5 = NULL;

  something_1 = malloc(SOME_SIZE);
  if (do_step_1(something_1) == BAD_RESULT){
    free(something_1);
    return;
  }
  
  something_2 = malloc(SOME_SIZE);
  if (do_step_2(something_2) == BAD_RESULT){
    free(something_1);
    free(something_2);
    return;
  }
  
  something_3 = malloc(SOME_SIZE);
  if (do_step_3(something_3) == BAD_RESULT){
    free(something_1);
    free(something_2);
    free(something_3);
    return;
  }
  
  something_4 = malloc(SOME_SIZE);
  if (do_step_4(something_4) == BAD_RESULT){
    free(something_1);
    free(something_2);
    free(something_3);
    free(something_4);
    return;
  }
  
  something_5 = malloc(SOME_SIZE);
  if (do_step_5(something_5) == BAD_RESULT){
    free(something_1);
    free(something_2);
    free(something_3);
    free(something_4);
    free(something_5);
    return;
  }
  
  do_all_the_things(something_1, something_2, something_3);
  do_things_after(something_3, something_4, something_5);
  
  free(something_1);
  free(something_2);
  free(something_3);
  free(something_4);
  free(something_5);
}

Then you might go "Well this is dumb too, let's just use a cleanup function":

void foobar(){
  char * something_1 = NULL;
  char * something_2 = NULL;
  char * something_3 = NULL;
  char * something_4 = NULL;
  char * something_5 = NULL;

  something_1 = malloc(SOME_SIZE);
  if (do_step_1(something_1) == BAD_RESULT){
    cleanup(something_1, something_2, something_3, something_4, something_5);
    return;
  }
  
  something_2 = malloc(SOME_SIZE);
  if (do_step_2(something_2) == BAD_RESULT){
    cleanup(something_1, something_2, something_3, something_4, something_5);
    return;
  }
  
  something_3 = malloc(SOME_SIZE);
  if (do_step_3(something_3) == BAD_RESULT){
    cleanup(something_1, something_2, something_3, something_4, something_5);
    return;
  }
  
  something_4 = malloc(SOME_SIZE);
  if (do_step_4(something_4) == BAD_RESULT){
    cleanup(something_1, something_2, something_3, something_4, something_5);
    return;
  }
  
  something_5 = malloc(SOME_SIZE);
  if (do_step_5(something_5) == BAD_RESULT){
    cleanup(something_1, something_2, something_3, something_4, something_5);
    return;
  }
  
  do_all_the_things(something_1, something_2, something_3);
  do_things_after(something_3, something_4, something_5);
  
  cleanup(something_1, something_2, something_3, something_4, something_5);
}

void cleanup(char * something_1, char * something_2, char * something_3, char * something_4, char * something_5){
  free(something_1);
  free(something_2);
  free(something_3);
  free(something_4);
  free(something_5);
}

Success! Now you have something that resembles structured code! Except... What if in reality we wanted to remove one of the somethings? Well dammit, now I have to redefine cleanup and remove that something from all of the function calls. Or what if I wanted to add yet another thing? Same problem

 

Or I could avoid this by using a goto statement:

void foobar(){
  char * something_1 = NULL;
  char * something_2 = NULL;
  char * something_3 = NULL;
  char * something_4 = NULL;
  char * something_5 = NULL;

  something_1 = malloc(SOME_SIZE);
  if (do_step_1(something_1) == BAD_RESULT){
    goto cleanup;
  }
  
  something_2 = malloc(SOME_SIZE);
  if (do_step_2(something_2) == BAD_RESULT){
    goto cleanup;
  }
  
  something_3 = malloc(SOME_SIZE);
  if (do_step_3(something_3) == BAD_RESULT){
    goto cleanup;
  }
  
  something_4 = malloc(SOME_SIZE);
  if (do_step_4(something_4) == BAD_RESULT){
    goto cleanup;
  }
  
  something_5 = malloc(SOME_SIZE);
  if (do_step_5(something_5) == BAD_RESULT){
    goto cleanup;
  }
  
  do_all_the_things(something_1, something_2, something_3);
  do_things_after(something_3, something_4, something_5);

cleanup:  
  free(something_1);
  free(something_2);
  free(something_3);
  free(something_4);
  free(something_5);
}

Result:

  • Objective
    • Fewer lines of code
    • Less places of code to touch should I need to add or remove one of the somethings
    • It's faster because function calls are expensive compared to an unconditional jump. Function calls have implicit instructions to save off the last state of the CPU before jumping and restoring it when returning. An unconditional jump is literally set the program counter register to a value.
  • Subjective
    • Looks cleaner. Seeing a whole lot of calls to a function with five plus arguments makes me go "why"
    • Arguably having a helper function to facilitate a single function is wasteful. Plus if you've organized your code so helper functions live in one part or in another file because you wanted to have helpers in a utilities file, you're now jumping around in source code moreso than using goto.
Link to comment
Share on other sites

Link to post
Share on other sites

7 minutes ago, Mira Yurizaki said:

Looks cleaner. Seeing a whole lot of calls to a function with five plus arguments makes me go "why"

I'd argue RAII in C++ would make it it look even cleaner, since those pointers are on the stack and would be deleted on return automatically ;) (but that is so not part of this discussion)

 

EDIT just kidding I just noticed the mallocs. I'm dumb.

Gaming build:

CPU: i7-7700k (5.0ghz, 1.312v)

GPU(s): Asus Strix 1080ti OC (~2063mhz)

Memory: 32GB (4x8) DDR4 G.Skill TridentZ RGB 3000mhz

Motherboard: Asus Prime z270-AR

PSU: Seasonic Prime Titanium 850W

Cooler: Custom water loop (420mm rad + 360mm rad)

Case: Be quiet! Dark base pro 900 (silver)
Primary storage: Samsung 960 evo m.2 SSD (500gb)

Secondary storage: Samsung 850 evo SSD (250gb)

 

Server build:

OS: Ubuntu server 16.04 LTS (though will probably upgrade to 17.04 for better ryzen support)

CPU: Ryzen R7 1700x

Memory: Ballistix Sport LT 16GB

Motherboard: Asrock B350 m4 pro

PSU: Corsair CX550M

Cooler: Cooler master hyper 212 evo

Storage: 2TB WD Red x1, 128gb OCZ SSD for OS

Case: HAF 932 adv

 

Link to comment
Share on other sites

Link to post
Share on other sites

9 minutes ago, reniat said:

I'd argue RAII in C++ would make it it look even cleaner, since those pointers are on the stack and would be deleted on return automatically ;) (but that is so not part of this discussion)

 

EDIT just kidding I just noticed the mallocs. I'm dumb.

And even then the "naive" solution in any other "advanced" language would've been to try-catch this, throw an exception on error, and clean up your resources in the catch or finally block.

Link to comment
Share on other sites

Link to post
Share on other sites

6 minutes ago, reniat said:

I'd argue RAII in C++ would make it it look even cleaner, since those pointers are on the stack and would be deleted on return automatically ;) (but that is so not part of this discussion)

 

EDIT just kidding I just noticed the mallocs. I'm dumb.

Why the striked-trough text? You are right, that is what RAII is all about:

 

void
foobar()
{
	auto something_1 = std::make_unique<char[]>(SOME_SIZE);
	auto something_2 = std::make_unique<char[]>(SOME_SIZE);
	auto something_3 = std::make_unique<char[]>(SOME_SIZE);

	if (do_step_1(something_1) == BAD_RESULT)
	{
    		return;
  	}
  
  	if (do_step_2(something_2) == BAD_RESULT)
	{
    		return;
  	}
  
  	if (do_step_3(something_3) == BAD_RESULT)
	{
    		return;
  	}
  
  	do_all_the_things(something_1, something_2, something_3);
}

 

No matter how en when the function is exited, the memory will always be cleaned up.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×