Welcome, Guest. Please login or register.
July 30, 2025, 03:29:09 PM

Login with username, password and session length

Search:     Advanced search
we're back, baby
*
Home Help Search Login Register
f13.net  |  f13.net General Forums  |  General Discussion  |  Topic: C/C++ Question 0 Members and 1 Guest are viewing this topic.
Pages: [1] 2 Go Down Print
Author Topic: C/C++ Question  (Read 6723 times)
Morat20
Terracotta Army
Posts: 18529


on: February 29, 2012, 06:55:20 PM

I am stumped. My current job is taking a bunch of C/C++ code (specifically -- old code written by a guy who learned C from a C++ book, and then modified and extensively changed by a guy who knew C a lot better than C++ -- in short, a hodge podge that's half class-driven and half straight up old school C and all mess) build on Borland Builder and moving the project to compile on something newer (in this case, Visual Studio 2008). We're moving it because Borland Builder has some weird linker issue thing wherein code past a certain size triggers a massive linker error, so the poor coder working on it spends more time externing shit to get around it than he does adding/fixing it.

This has been...a challenge. Borland Builder is fucking weird in the shit it allows, and a lot of stuff that skated by with warnings is now "errors" (including stuff like multiple variable definitions and the like) and I'm having to do a shit ton of work. 95% of it relates to string handling and the fact that I'm also moving it to Unicode, but that's neither here nor there.

Getting to the problem -- I straightened out a giant heaping problem related to a set of cpp files that defined global variables, poiinters, and something else I can't recall -- moved them to headers, insured they were only included ONCE (as opposed to, you know, multiple times like they were. How the fuck that worked I cannot tell you).

In cleaning up the #include statements, I have finally gotten to something that looks like this

main.cpp
#include "global variables.h"
#include "useful definitions.cpp"
#include "example.cpp"


example.cpp
//Lots of Code
//if (this thing is true)
#include "common_code_block.cpp"   THIS IS THE BITCHING PROBLEM.
//else

common_code_block.cpp
variable_defined_globally = blah;  //IT CAN'T SEE THIS FUCKER, WHICH IS DEFINED IN GLOBAL_VARIABLES.H
blah + blah;
//more code.

(In short, common code block uses a global variable defined in a header file two files up)

See that #include there? It's a .cpp file that is JUST a chunk of code. Not a function, not anything. Just a goddamn chunk of code, sitting there -- ripped out from that if statement and thrown into a .cpp file because another module uses that same rather hefty chunk of logic. Not even functionalized.

That? That shit does not compile properly because of those global variables I mentioned upthread.

Except when "example.cpp" gets called, it can't see "global variables.h" (the code block that got yanked out uses some of the global variables) but CAN see the damn definitions. Or vice versa.  IT should be able to see it, but doesn't. (It certainly did under Borland Builder, but of course I had to do a massive reorg job because Borland Builder somehow multiply included global_variables.h and not only allowed it to compile, it somehow worked. They're not extern'd, either -- it should have made multiple instances of those damn things. And since it gave a warning, I guess it did. It just somehow worked.

Obviously I can't #include the global_variables.h file in the common_block.cpp file -- I get multiple definition errors for very good reason.

So my problem: I've never actually used a #include as a method of just, you know, exporting a giant chunk of logic. Frankly, it would have never occured to me to do something like that. I'd have made it a goddamn function and, you know, passed shit in by reference. But the previous guy (who did this like 10 years ago) just cut and pasted the damn thing from one file to another. (And this isn't the only place).

So why the heck can't common.cpp see the global variables? And is there an actual term for the process of yanking all that shit out turning 100 lines of raw, unfunctionalized code into a #include and just slapping it into the program like some giant-ass macro?

Maybe there's some awesome I'm not seeing here, because it LOOKS like the world's worst way to do this and is not biting me on the ass. I can, if I have to, cut and paste the fucker back. But it's called "common code block" for a reason, and my collegue (who maintains and expands this, where I am currently ass deep in porting it to work in a compiler that's, you know, made by a company that still exists and upgrades and supports it) doesn't want to have to modify it in a half dozen places each time he has to change something in that file (and it's sister files, also done in the same way).

I really don't have the time to properly functionalize it -- frankly, I don't understand the code well enough to do it with any speed and "getting it done" is the current order of the day, not "fixing bad decisions from the past". So unless there's some trick to this weird "treat an include statement like a giant macro" metho or some compiler flag, all I can think of to do is cut and paste it.

Which gets to the question at hand:

1) Does anyone know why that cpp file might not be able to see the global variables?
2) Was this weird ass #include thing a common trick or concept I somehow just never saw?
3) Is there a fucking term for it, so I can google the damn thing more effectively and answer this sort of shit in the future? Because I can promise you that googline "Problems with an include file we made by yanking a ton of raw code out and slapping it into a new file" has not seen much success.

I've spent WAY the heck too much time straightening out the rat's nest of the header files and compiler order of the basic common includes as it is. I'm about to beat my PC with a bat. I'm at my wit's end, and I hope someone can help. Or at least assure me that it's a stupid way to do it in the first place, so I don't feel bad about cutting and pasting the shit back and telling my colleague we can make proper functions later.
Samwise
Moderator
Posts: 19324

sentient yeast infection


WWW
Reply #1 on: February 29, 2012, 11:00:25 PM

1) Does anyone know why that cpp file might not be able to see the global variables?

If I had the code in front of me, I'd be checking the obvious stuff first -- can a statement right before or after the #include access the global variables, for example?  I'm wondering if maybe they aren't actually declared properly in the header and this #include thing is a red herring.  The #include is preprocessor and shouldn't affect scoping.

Quote
2) Was this weird ass #include thing a common trick or concept I somehow just never saw?

It's atypical, but AFAIK perfectly valid and should work the same everywhere.  #include really just means "effectively copy and paste this file's entire contents right here".  Usually you use it with header files to copy class definitions around but that's really just convention; you can do it with any arbitrary block of code anywhere you like.  I think.

That said, it's pretty weird and confusing.  The way I'd probably do it (besides the obvious of putting that code in a reusable function, if for no other reason so that it doesn't need to be redundantly compiled multiple times) would be to put that common code in a header file as a macro, e.g.:

#define COMMON_CODE_BLOCK  int foo = 1;\
int bar = 2;\
doStuff( foo, bar );\
etc...

and then #include that header file up top (where headers usually go) and stick the COMMON_CODE_BLOCK macro in my actual code.  Still kinda weird but less so than having an #include in the middle of a function.

Quote
3) Is there a fucking term for it, so I can google the damn thing more effectively and answer this sort of shit in the future? Because I can promise you that googline "Problems with an include file we made by yanking a ton of raw code out and slapping it into a new file" has not seen much success.

I'd google around the terms "transclusion" and "scope" and of course "C++".
Miguel
Terracotta Army
Posts: 1298

कुशल


Reply #2 on: February 29, 2012, 11:08:59 PM

Yes it's a stupid (if not illegal) way to do this sort of thing.  #include just takes the text of the file and includes it verbatim into the referenced file.  You often see stuff like this from people with backgrounds in embedded programming, where your data and text regions hold only a few precious bytes and *every byte of code counts*.  Remember that each and every function call creates an activation record and a frame that gets pushed onto the stack:  if you only get 128 bytes of stack space, that's only 8 nesting levels before you are hosed (especially if you declare a lot of local variables, which also get pushed onto the stack).  Embedded C programmers have to learn all of these tricks when you're writing code destined for a $3 processor with severe limitations like this. But I digress....;)

You really need to see what the output of the preprocessor looks like.  For GCC it would be the -E flag.  Your compiler may be resolving the dependency chain in a recursive fashion which means the #if may include the code first, then resolve references locally before all of the #includes are done.  In any case, looking at the output of the preprocessor will tell you what your compiler/lexer see's after all of the preprocessor directives are expanded/processed.  It will probably become apparent that there is a scoping or order of evaluation problem that you can then fix.

“We have competent people thinking about this stuff. We’re not just making shit up.” -Neil deGrasse Tyson
Morat20
Terracotta Army
Posts: 18529


Reply #3 on: March 01, 2012, 05:29:36 AM

Thanks. That'll help.

And yeah, the guy that did this originally was an embedded guy if I understand the code's history properly. One of the thing that annoys me about VS2008 is I'm not entirely sure what order it's compiling things in. That preproccessor flag should be a godsend.

And the obvious "check to see if the global variable can be seen prior to the #include block" did not, in fact, occur to me. I blame two days of frustrating detangling on that.

It's going on my list to "fix properly later" if there's ever room in the development schedule. If you're going to use global variables like that, at least create a class to hold them, make them static, and then you can just create an instance and use the values that way. As long as you remember to initialize it at the beginning of your code. :)

I appreciate the help. You've hopefully saved me several more hours of headaches.
Paroid
Terracotta Army
Posts: 17

More Grief Titles Than Posts


Reply #4 on: March 01, 2012, 08:11:48 AM

If I understand this code architecture correctly, main.cpp is using #include directives to include the code from the other .cpp files.  Are you getting errors when compiling main.cpp or example.cpp/common_code_block.cpp?  Any .cpp which is designed to be #included is probably not supposed to be compiled by itself, and would give errors.
ezrast
Terracotta Army
Posts: 2125


WWW
Reply #5 on: March 01, 2012, 09:55:09 AM

If I understand this code architecture correctly, main.cpp is using #include directives to include the code from the other .cpp files.  Are you getting errors when compiling main.cpp or example.cpp/common_code_block.cpp?  Any .cpp which is designed to be #included is probably not supposed to be compiled by itself, and would give errors.
I bet this guy's got it. What happens if you change the name of common_code_block.cpp to common_code_block.h?
(edit: or otherwise explicitly ensure common_code_block.cpp isn't being compiled as its own module - I think just changing the extension does that in MSVS but it's been a while)

Getting to the problem -- I straightened out a giant heaping problem related to a set of cpp files that defined global variables, poiinters, and something else I can't recall -- moved them to headers, insured they were only included ONCE (as opposed to, you know, multiple times like they were. How the fuck that worked I cannot tell you).
That can work just fine if your headers look like
some_header.h:
#ifndef SOME_HEADER_H
// all your include stuff...
#define SOME_HEADER_H
#endif

It should allow you to throw as many "#include some_header.h" directives into your code as you want without getting errors for defining things multiple times.
« Last Edit: March 01, 2012, 10:29:00 AM by ezrast »
Amarr HM
Terracotta Army
Posts: 3066


Reply #6 on: March 01, 2012, 10:12:41 AM

Are you calling the global_variables with the scope resolution operator? You may have this but it wasn't in your pseudo code, should look like this global variables::variable_defined_globally. I'm assuming here they are static.

I'm going to escape, come back, wipe this place off the face of the Earth, obliterate it and you with it.
Samwise
Moderator
Posts: 19324

sentient yeast infection


WWW
Reply #7 on: March 01, 2012, 10:14:09 AM

That can work just fine if your headers look like
some_header.h:
#ifndef SOME_HEADER_H
// all your include stuff...
#define SOME_HEADER_H
#endif

It should allow you to throw as many "#include some_header.h" directives into your code as you want without getting errors for defining things multiple times.

Header guards are crutches for people who can't be bothered to think about their dependencies.   Oh ho ho ho. Reallllly?
proudft
Terracotta Army
Posts: 1228


Reply #8 on: March 01, 2012, 10:16:44 AM

Random shot in the dark - you might be having a name munging problem with C and C++ disagreeing about what to call the variables.   If that include file is processed in a C file before it hits the C++ you have, the compiler might decide to stick with C format for the rest of the compile and thus C++ can't see them.   Wrapping the definitions (well, really, the #include line in this case) in an extern "C" { } block within the C++ code will fix that.

« Last Edit: March 01, 2012, 10:19:46 AM by proudft »
ezrast
Terracotta Army
Posts: 2125


WWW
Reply #9 on: March 01, 2012, 10:27:27 AM

Header guards are crutches for people who can't be bothered to think about their dependencies.   Oh ho ho ho. Reallllly?
Ha. Knowing people think like this makes me happy I didn't decide to be a programmer. *shudder*
Samwise
Moderator
Posts: 19324

sentient yeast infection


WWW
Reply #10 on: March 01, 2012, 10:38:27 AM

Header guards are crutches for people who can't be bothered to think about their dependencies.   Oh ho ho ho. Reallllly?
Ha. Knowing people think like this makes me happy I didn't decide to be a programmer. *shudder*
Don't worry, people that think like me are in the minority.  

Most programmers just sort of roll their faces on the keyboard until it compiles.
« Last Edit: March 01, 2012, 10:41:23 AM by Samwise »
Tarami
Terracotta Army
Posts: 1980


Reply #11 on: March 01, 2012, 11:52:01 AM

Most programmers think most programmers do that. Ohhhhh, I see.

- I'm giving you this one for free.
- Nothing's free in the waterworld.
Morat20
Terracotta Army
Posts: 18529


Reply #12 on: March 02, 2012, 05:58:20 AM

I spent yesterday playing "cut and paste" with the code and seperating out all the class definitions into proper .h and .cpp files. (Finding, in the process, an entire "common" file that consisted of four seperate classes, three of them as header declarations one as a full class declaration -- two of which used each other int he constructor. How the fuck Borland ever compiled this mess I don't know. I made seperate files for them, forward declared the classes, and moved on to finding all the goddamn method declarations and moving them into properly named .cpp files so I can see what the fuck is going on).

That top about the preproccessor block helped -- the problem, once I spent six hours cleaning up the code into something that could be traced by the human brain, boiled down to those damn massive global variable and pointer files. MSVC needed the global variable headers in those code blocks to handle that compilation set.

Including them, of course, throws a multiple definition and reinitialization error. Which in Borland is apparently only a warning. (And no, they're not guarded). So yeah, apparently they've been ignoring a zillion "X is already defined and declared, doing it again" warnings. How this even works is beyond me.

So I spent the last two hours of yesterday -- and will all of today -- taking the massive ass global variables (hundreds) and global pointers (also hundreds) and externing them in the .h file, initializing them in the .cpp file so the .h can be included as needed without allocating and defining the suckers.

I want to shoot the guy that made all this. In his defense, he was a Fortran guy whose only non-Fortran experience was embedded systems, and he wrote this ten years ago when learning C/C++ from a book. It's still a massive fuckup and I have to go tell my boss -- WHO IS THAT GUY -- that the problem is MSVC will not let you shoot yourself in the foot to the extent that Borland will.

It's not an easy task to explain that the conversion is taking forever because the code was written in what might, if you squint, been almost marginally acceptable 10 to 15 years ago, but that MSVC and I would expect g++ and practically anyone would scream bloody murder about.
Lantyssa
Terracotta Army
Posts: 20848


Reply #13 on: March 02, 2012, 07:03:18 AM

"Boss, it's spaghetti code."

Hahahaha!  I'm really good at this!
Morat20
Terracotta Army
Posts: 18529


Reply #14 on: March 02, 2012, 09:03:34 AM

HIS spaghettti code.
Lantyssa
Terracotta Army
Posts: 20848


Reply #15 on: March 02, 2012, 09:45:53 AM

Well, yeah.  But instead of tap-dancing around it, be honest.  You've got to spend a ton of time sorting out the code he wrote.  If he's unhappy with that, he should have written it better.

Hahahaha!  I'm really good at this!
Samwise
Moderator
Posts: 19324

sentient yeast infection


WWW
Reply #16 on: March 02, 2012, 11:25:53 AM

If it's something he wrote while learning C++, he's probably perfectly aware that it's a fucking wreck.  God knows I feel ashamed when I look back at the stuff I wrote ten years ago.
Morat20
Terracotta Army
Posts: 18529


Reply #17 on: March 02, 2012, 05:22:36 PM

This has been one of the most frustrating weeks of my career. I'm not sure I've accomplished ANYTHING other than confusing myself.

It's like every bad coding practice ever is coming home to roost -- Borland Builder must be a highly permissive compiler compared to MSVC, because this appears to be a structural problem.

I've managed to break out the classes. I've externed the global variables, pointers, prototypes, what-the-fuck ever into .h files and initialized them in the .cpp files. Except some of those global variables are arrays that later get called using sizeof() operaters, but the arrays are defined in the header as black sized.

There's ridiculous uses of anonymous enum types -- which I keep getting multiple definition issues with, so I've added code guards to everything. Which later led to a fun recurvise fuck-up in a class definition that had me banging my head against the wall.

Basically the problem is the design is for shit. Absolutely for shit. In trying to do all this "common" shared code, instead of making proper classes they went with a zillion global variables that are referenced everywhere, overwritten, defined again...apparently Borland doesn't even BOTHER checking a whole bunch of shit (or if it does, it came across as warnings that were ignored not errors that have to be fixed).

And I admit, I have NOT helped the situation by breaking everything apart and putting it back together in a sane way (you know, classes in their own files, etc). So I've been stepping on my own foot in the process.

Everytime I fix one goddamn thing I get ANOTHER set of "multiple definition" errors, or complaints that no constructor exists, or all sorts of weird-ass complaints that are of the fun variety of "This isn't the actual problem. This is a problem caused by a fuck-up upstream". And I get to try to figure out whether I caused this problem, or just uncovered it because the compile process moved forward.

I think -- and as usual, this occurs to me on Friday when driving home (you know, because I had to stop dicking around and think) that with the changes I've already made I *think* I have a possible solution. At least I can say that after this week, I'm very familiar with the way this piece of shit works.
Lantyssa
Terracotta Army
Posts: 20848


Reply #18 on: March 02, 2012, 07:33:23 PM

It's like every bad coding practice ever is coming home to roost -- Borland Builder must be a highly permissive compiler compared to MSVC, because this appears to be a structural problem.
I can't talk about newer versions, but Borland C++ 4.x was shit.  gcc using Cygwin would be a step up.  It's possible it was great for experienced hacks, but as self-taught with a background where I learned coding by experimenting, it was a terrible compiler choice.  Trying to convert code to compile elsewhere threw countless errors.  Usually it was easier to just rewrite it from scratch.

(Not that my early C code was all that well written either...)

Hahahaha!  I'm really good at this!
Evil Elvis
Terracotta Army
Posts: 963


Reply #19 on: March 02, 2012, 09:22:13 PM

Borland XE is shit too, although not nearly as bad as Borland 5.  Thankfully I only have to deal with it for a few small applications, but I loathe every minute of it.

There's a huge program at my work that displays so many warning messages - including those multiple definition warnings that the developers evidently think is just fine to ignore - that you can't compile all the projects in the group in one go; it hangs the IDE.

At least you're not so dependent on VCL that you're unable to switch to MSVC++.
Sheepherder
Terracotta Army
Posts: 5192


Reply #20 on: March 03, 2012, 01:50:49 PM

"Boss, it's spaghetti code."

"Like a yak stopped in the middle of the freeway to give birth."
Morat20
Terracotta Army
Posts: 18529


Reply #21 on: March 03, 2012, 08:21:10 PM

"Boss, it's spaghetti code."

"Like a yak stopped in the middle of the freeway to give birth."
There comes a point, however, where you can't keep saying "Boss, this code is shit" without sounding like you're just making excuses. At least now I'm in the code the OTHER coder regularly uses who can attest that it is, in fact, kinda shitty.

Plus he can verify that they have indeed been ignoring eighty-three million "Multilple Definition/Reinitialization" warnings.
Soulflame
Terracotta Army
Posts: 6487


Reply #22 on: March 03, 2012, 11:18:19 PM

Can you reimplement it from the ground up?  It'd probably be easier than fixing something that old.
Morat20
Terracotta Army
Posts: 18529


Reply #23 on: March 04, 2012, 07:34:22 AM

Can you reimplement it from the ground up?  It'd probably be easier than fixing something that old.
It's been discussed, but it doesn't fit into the development cycle.

Another module of the code, that I'm going to be responsible for, I am going to be slowly reimplementing -- thankfully it was done in an almost correct C++ fashion (I've already converted that module to MSVC) so I can fix it in place.

I think the module I'm currently working on might get slated for a heavy rework about 18 months from now. Maybe. Problem is, end users don't really see the effects of a major reimplemntation so it's hard to sell to them. I think the best we're getting is what I'm doing now -- tearing apart the files and restructuring them into proper C++ files and fixing the global variables/pointers/prototypes shit.

Plain fact of the matter is, what I'm doing is basically GUI work for some FORTRAN stuff. The fortran stuff -- seriously pricey, 4-figures per seat sort of data and analysis packages -- is the important stuff. The GUIs, the plotting stuff -- kinda just access tools. The fortran folks add new equations and models regularly, we try to keep up.
Jeff Kelly
Terracotta Army
Posts: 6921

I'm an apathetic, hedonistic, utilitarian, nihilistic existentialist.


Reply #24 on: March 05, 2012, 08:49:41 AM

Oh the joys of embedded coders. I can relate.

The problem is not really that programming an embedded system is somehow different, because it doesn't have to be. It's mostly that embedded development has for decades been the playing field of self-taught programmers/engineers and of a lot of people that came to programming not out of choice. They learned programming because what was once an entirely electrical, hydraulical or mechanical system designed by serious engineers has slowly turned into a small embedded computer box with lots of sensors and actuators attached to it. Yet, in most companies I know, the same electrical, mechanical and process engineers that once designed the purely analogue systems are still around and develop code for the embedded systems that replaced them, except they'd rather not do that.

A CTO for the global market leader in brake systems once said to me that "we design brake systems here, not computers" after I asked about the software development processes and expressed my opinion about how outdated they were. This from a guy that had to oversee the development of complex antilock braking control systems or electronic stability control systems with a serious amount of code attached to it and severe safety requirements and repercussions.

For most of my professional life I have been the sole computer scientist/computer engineer in the whole company, regardless of the company I worked for. The companies are run by engineers that never wanted to write code or develop software and just kind of slid into it. They treat it as an afterthought, for them the "real" system is the bits of electronic equipment and wires, they employ more people for hardware design and construction than they do for software and it shows. You always lose when you argue with them that you need a certain spec'd component because it would "make the software run better". The same mindset that did Nokia in in the end.

I've worked for companies that had "version/revisioning with CVS on the agenda for next year"  in 2007, who still had the majority of their code base in embedded assembly written for a compiler toolchain by a company that went out of business a decade ago, who "will get around to port it to C eventually".

Who never heard of static code checking, god forbid something as recent as unit testing.

That's why for example the automotive industry basically mandates an entire development process for every supplier that wants to do business with them.

There are only entirely reasonable (some might say "well, duh") things in there like

Gather requirements
Ensure traceability of requirements and code
do static code checking, oh and we've even made you a handy ruleset so you won't have to bother
Use a software development model, ANY ONE WILL DO, just use one, pretty please.
do testing
let the testing be done by different people than the development
document everything
use version control/revision control
use only certified tools

Granted they call it Automotive Spice because it sounds better, but still.

Yet I had to fight for every single one of those things in nearly every company I've worked for from small town business to global market leader. They usually only budge when you tell them that they kinda agreed to do those things when they entered the contract with the Car Maker and  if you read to them the kind of trouble they are in if they don't do it. (Like: you'll pay millions of Euros and likely lose your company kind of trouble)

That's why Software Powerhouses like Microsoft, Apple or Google run circles around entire industries if they decide to develop products for them.

If they ever decided to build In-Car-Control/In-Car-Entertainment systems then the majority of companies in that sector will go out of business in a heartbeat. It's like your side is still drunk on the invention of the rock attached to a stick while the other side's mechanized infantry rolls in to kick your ass. (Although if Civ is any indication I kinda want a phalanx in that case)
naum
Terracotta Army
Posts: 4263


WWW
Reply #25 on: March 05, 2012, 12:56:11 PM

I never did much C++ programming (other than building some "toy" programs and reading through introductory texts), but I did a great bit of C programming. Though most of my "C programming" involved puzzling out API docs and examining the esoteric "sample" programs that always seemed to feature some obscure function devoid of any pragmatic benefit. And most of my work was in data communication platforms.

"Should the batman kill Joker because it would save more lives?" is a fundamentally different question from "should the batman have a bunch of machineguns that go BATBATBATBATBAT because its totally cool?". ~Goumindong
Zetor
Terracotta Army
Posts: 3269


WWW
Reply #26 on: March 05, 2012, 09:48:41 PM

My company does hw/sw security evaluation, and there have been some truly awesome, for real things I've personally encountered when going through (for example) mobile phone baseband software -- it's the 20th century all over again.

For example, in almost every project there was someone who thought using fixed-size buffers and copying raw unchecked user input into it is a splendid idea. The reactions from the developer when we sent the vulnerability list back to them was amusing too. "Oh, so you say that using a char[8] is bad and can lead to a buffer overflow? No problem, I'll increase it to a char[100] and we'll be safe for sure!" Never mind that user input copied into that buffer can be up to 65535 bytes long...

Morat20
Terracotta Army
Posts: 18529


Reply #27 on: March 06, 2012, 05:27:12 AM

Finally sorted the fucker out. FINALLY.

I had to go ahead and shove the #include "blahdy-blah" stuff right back into the code. It simply wouldn't compile otherwise. Luckily, all that "common blocks" and "common shit" was like 95% actual class methods or went INTO class methods -- classes that were already common between modules!

So it's not actually adding any time to development, because there's still only the one copy.

I code-guarded the fuck out of everything, segregated everything into readable and sanely named and situated files, consolidated classes, and basically did the job as properly as I could without going much beyond "cut and paste". Then I changed entirely how the damn thing started up so it does so in a sane way, and was able to get everyone to see the globals and only initialize the suckers once.

Now all I have is the 8 million lines of string literals I have to surround with a Macro to make it unicode compliant. Yay, wxWidgets and your total failure to overload the = operator, because "wxString = "This is a wxString" is too goddamn easy when you can do wx String = wxT("This is a literal.") Admittedly, the latest and greatest version of wxWidgets I think does support that. But I'm working with very old versions.

Mind you, they're using three difference versions. My next job is going to be updating those damn libraries and fixing the code so at least everyone is using the same damn wxWidgets version.

Anyways, thanks for the help guys. Between you and frantic googling, I got this done in far less time than I'd feared.
Miguel
Terracotta Army
Posts: 1298

कुशल


Reply #28 on: March 06, 2012, 07:56:53 AM

Oh the joys of embedded coders. I can relate.

The problem is not really that programming an embedded system is somehow different, because it doesn't have to be. It's mostly that embedded development has for decades been the playing field of self-taught programmers/engineers and of a lot of people that came to programming not out of choice.

That certainly part of it, but I think it goes deeper.

A lot of software engineers don't understand how what they write ends up as machine code.  They don't, for example, understand the ramifications of design and how it impacts the translation from code to the machine.

Take virtual methods for example.  It's a very basic concept, and any object oriented programming book/class covers the essentials of "virtualness" and other related subjects like covariance and contravarience.  However the decision to declare virtual methods has certain...side effects.  One such side effect is that you now have a greatly expanded virtual method table that gets glued on each and every instance so that the runtime type of the object can be unwound.

So you end up seeing stupid stuff like virtual methods sprinkled throughout the code almost as if done randomly, and pass by value being used in object methods, and you end up getting tons and tons of object copies happening.  Maybe fine on a regular PC with 8GB of RAM, but on an embedded platform with a small main memory and a tiny stack, certain death with almost impossible to debug side effects (ever seen a stack trace taken in gdb once the stack has overflowed, and gdb tried to symbolcate the resulting mess?).

The hard part is these things are hard to put in book format, because the resulting "rules" are highly platform and compiler specific.  But one really has to dig down at this level of detail when working on simple (yet powerful) embedded architectures.

Good thing is that I'm seeing more and more embedded programming courses being taught both at universities and online, and they are being taught by experienced computer engineers, who know to say "yes, this is what your CS book says, but here's *why* it says that".

“We have competent people thinking about this stuff. We’re not just making shit up.” -Neil deGrasse Tyson
Margalis
Terracotta Army
Posts: 12335


Reply #29 on: March 06, 2012, 08:08:22 PM

Everyone should be required to do some PS3 programming. (Or anything cell-based I suppose)

vampirehipi23: I would enjoy a book written by a monkey and turned into a movie rather than this.
Murgos
Terracotta Army
Posts: 7474


Reply #30 on: March 07, 2012, 04:30:52 AM

Everyone should be required to do some PS3 programming. (Or anything cell-based I suppose)

Why not just say multi-core or multi-processor?  Why Cell in particular?  Is there something in that architecture you feel is going to be important for people to know for the future?

"You have all recieved youre last warning. I am in the process of currently tracking all of youre ips and pinging your home adressess. you should not have commencemed a war with me" - Aaron Rayburn
Margalis
Terracotta Army
Posts: 12335


Reply #31 on: March 09, 2012, 02:08:08 AM

Why not just say multi-core or multi-processor?  Why Cell in particular?  Is there something in that architecture you feel is going to be important for people to know for the future?

Cell is one shitty main CPU and a bunch of super fast specialized chips with no access to main memory and tiny dedicated memory you have to DMA to. It breaks vtables and really does not play well with object oriented programming.

The way the cell SPEs work is you feed them an input stream of data and they transform and output, similar to a GPU. (It's quite similar to general purpose GPU computing actually)

That forces you to think in some different and interesting ways. It means you need data structures that are packed carefully and laid out in contiguous memory, which has side effects like being incredibly cache friendly and super efficient in both speed and memory. Programming for cell is not like OOP C++ programming or really even C programming, at the fundamental level ideally you're thinking about how to package and transform data rather than about classes and methods. Basically the fundamental unit of C++ programming is a class and the fundamental unit of cell programming is a byte stream.

I don't know if that sort of stuff will be directly applicable going forward but it does expand the mind and things that work on cell will work efficiently on any architecture. For example on the 360 2 hardware threads share the same cache, meaning that if you can write an algorithm that works on packed contiguous data things will run a lot faster.

But because the 360 has one unified memory for the most part you just derp around and write loops that make a million virtual function calls.

It's just something everyone should experience, like functional programming.

Super nerd mode engaging: warning!

Say for example you were working on a system where each actor in your scene was going to sample some points in your scene each frame in order to retrieve harmonic spherical lighting coefficients that it can weight and lerp to end up with some environmental fake GI shit. To do that on cell you need access to those coefficients and a way to look them up to to look them up they are arranged in something like a quadtree / octree / sphere tree. So conceptually you want to take a bunch of positions and feed them into an SPE along with some sort of flattened oct tree or something that you can batch in from main memory in chunks. You also have to pay attention to stuff like byte boundaries.

So maybe you want to sort the actors in such a way that ones in similar parts of your tree end up together, then send an SPE those actors along with some flattened part of the tree that is relevant to them, then you send over the next positions and further tree parts, etc. And of course none of these things you are sending over are actual objects with handy methods like getChildAt() or getHSLCoefficients() but rather id numbers and implied structure (like a array-based heap) and such. And you have to think about how to batch your DMA calls and write algorithms where the SPE can do work while more memory is being DMA'd etc.

On the 360 you'd probably just write a for loop that was like:

for each actor
  tree->getCoefficients(actorPosition)

One thing it really forces you to think about it what sets of data you have in your application, rather than something like class hierarchy in which data is somewhat implicit.
« Last Edit: March 09, 2012, 02:21:07 AM by Margalis »

vampirehipi23: I would enjoy a book written by a monkey and turned into a movie rather than this.
Morat20
Terracotta Army
Posts: 18529


Reply #32 on: March 12, 2012, 05:30:34 PM

So, I finally get to a working executable. This requires rebuilding the base libraries, oh, a zillion times because I forgot to set one compiler flag on one tiny module so of course it won't link properly.

The executable crashes, of course, instantly. I even know why.

Basically I've got this:

globals.h
extern string MyString[2];

And I use that everywhere.

I've got a class, call it:
MyApp.cpp
MyApp::OnInit()
"Do stuff"

My question is -- how do I initialize MyString = {String 1,String2}; I want it to be so I could just make a global.cpp file that had all the inits in it, and #include the sucker at the top of MyApp -- or hell, wherever.

Unfortunately, that's not working -- I get a lovely <bad ptr> when it goes to do the MyString={stuff, stuff} part. So, you know, it's got no actual space -- it's never initialized, it's just going to assign it.

I'm too tired to figure it out tonight, but if anyone sees the obvious I'm missing, let me know. I spent WAY too much time tracking down fucked-up linker errors. (Including one bug that is NINE YEARS OLD and only occurs with these libraries under MSVC -- I'm lucky as hell I stumbled across the bug report, since the libraries are -- you know -- nine years out of date and I'm not allowed to update them as part of this project).
Miguel
Terracotta Army
Posts: 1298

कुशल


Reply #33 on: March 13, 2012, 03:41:13 PM

What type does "string" resolve to?  Is it char *? Or perhaps char[]?

“We have competent people thinking about this stuff. We’re not just making shit up.” -Neil deGrasse Tyson
Samwise
Moderator
Posts: 19324

sentient yeast infection


WWW
Reply #34 on: March 13, 2012, 05:04:55 PM

Somewhere outside of any function (compiled once) you have a:

string MyString[2];

that defines that array, right?  (As opposed to the "extern" statement declaring it that you include and therefore compile everywhere.)  I assume that if you didn't have that you'd get an error at link time.  That should be what allocates the space for the two "string" objects.  Could it be that it's the assignment operator in your string class that's barfing because it's trying to clean up a hunk of uninitialized memory (e.g. it's trying to delete() an uninitialized pointer)?

I'd be inclined to avoid the whole problem by making your two string dealy an object rather than an array.  Objects have constructors; arrays do not.   awesome, for real  Then you can just be like:

StringPair MyStringPair;

and your StringPair constructor will get called at the right time and do the right thing.  I think.
Pages: [1] 2 Go Up Print 
f13.net  |  f13.net General Forums  |  General Discussion  |  Topic: C/C++ Question  
Jump to:  

Powered by SMF 1.1.10 | SMF © 2006-2009, Simple Machines LLC