Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Sidesaddle Cavalry
Mar 15, 2013

Oh Boy Desert Map
From what I could tell at the career fair earlier this week, certain companies local to where I go to school seem to make a lot of devices where C is important. Motorola Solutions, for one.

whoops page snipe. i don't really know if that's a fact, though.

Adbot
ADBOT LOVES YOU

Vanadium
Jan 8, 2005

Yeah C remains important, and I don't really want to poo poo on the language too much, it just requires people to put up with a lot of bullshit. I wouldn't wanna talk anyone out of learning it.

Absurd Alhazred
Mar 27, 2010

by Athanatos
It's hard to really get a handle on the low-level stuff if you don't see it early. And it's easier to appreciate the benefits of newer languages/libraries if you see how lovely the old ones were.

Plus, you are very likely to run into a library that uses the old poo poo somewhere, and it's good to have some sense of these peculiarities starting out.

I do appreciate learning all the way down to assembly language when I was in high school and undergrad, and even digital system design, although I think a project where we would actually write a tiny bit of machine code would have been really neat.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

I think I'd rather teach assembly than C, though I spent at least a decade writing large-scale C code on purpose and with a smile. But yeah, it's still useful. Oh well.

Jeffrey of YOSPOS
Dec 22, 2005

GET LOSE, YOU CAN'T COMPARE WITH MY POWERS

Subjunctive posted:

Why do they even let beginners use C?
because you aren't allowed to use cool abstractions until you can build them yourself :colbert:

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Sure, but why let them test out of machine code via hexl-mode?

Jeffrey of YOSPOS
Dec 22, 2005

GET LOSE, YOU CAN'T COMPARE WITH MY POWERS
C is like portable machine code. The, uhh, register allocator isn't a good intro lesson I'm afraid.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Naive register allocator is super easy: assume that only stack and pc pointers are preserved across load/operate/store "instructions". It's slow, but it's what everyone's first compiler does to start.

Volte
Oct 4, 2004

woosh woosh
It's like they say: you can't build anything with LEGO until you've mastered injection moulding.

F_Shit_Fitzgerald
Feb 2, 2017



I have a question about getting a value at a specific position in a std::list. Full disclosure: this is part of a homework assignment, but it's only one part of it (in other words, getting a value isn't the entire assignment). If this is against the rules of the thread, I'll withdraw the question.

The task at hand is to convert a program from using a dynamic array to std::list. One of the functions takes a single parameter, an unsigned int, and is supposed to return a value (of another class type) in the array at the specified position.

After looking it up on cplusplus.com, my solution was to do something like this:

C++ code:
const customClass* getValue(unsigned int i) const {
     auto it = dataList.begin();
     return std::advance(begin, i);
}
The problem is that this won't compile. Code::Blocks complains that "void value not ignored as it ought to be".

Is there a better way to do this that actually compiles?

Fergus Mac Roich
Nov 5, 2008

Soiled Meat

F_Shit_Fitzgerald posted:

I have a question about getting a value at a specific position in a std::list. Full disclosure: this is part of a homework assignment, but it's only one part of it (in other words, getting a value isn't the entire assignment). If this is against the rules of the thread, I'll withdraw the question.

The task at hand is to convert a program from using a dynamic array to std::list. One of the functions takes a single parameter, an unsigned int, and is supposed to return a value (of another class type) in the array at the specified position.

After looking it up on cplusplus.com, my solution was to do something like this:

C++ code:
const customClass* getValue(unsigned int i) const {
     auto it = dataList.begin();
     return std::advance(begin, i);
}
The problem is that this won't compile. Code::Blocks complains that "void value not ignored as it ought to be".

Is there a better way to do this that actually compiles?

For solving your immediate problem: take a look at the function signature of std::advance. You can ignore the template parameters. What can you tell about the function from this?

void advance( InputIt& it, Distance n )

F_Shit_Fitzgerald
Feb 2, 2017



Fergus Mac Roich posted:

For solving your immediate problem: take a look at the function signature of std::advance. You can ignore the template parameters. What can you tell about the function from this?

void advance( InputIt& it, Distance n )

That it requires a const_iterator? I changed that in the code, and it accepted the line declaring the list iterator.

In other words:

code:
std::list<customClass*>::const_iterator it = dataList.begin();
...was accepted, but this is still blowing up the compiler:
code:
customClass* foo = std::advance(it, i);
return foo;

Doc Block
Apr 15, 2003
Fun Shoe
Look at the return type of advance

F_Shit_Fitzgerald
Feb 2, 2017



Doc Block posted:

Look at the return type of advance

Oh. I was so busy trying to find a solution that I missed that completely.

Thanks for the help! Back to the drawing board.

MutantBlue
Jun 8, 2001

F_Shit_Fitzgerald posted:

Oh. I was so busy trying to find a solution that I missed that completely.

Thanks for the help! Back to the drawing board.

Perhaps std::next

VikingofRock
Aug 24, 2008




F_Shit_Fitzgerald posted:

Oh. I was so busy trying to find a solution that I missed that completely.

Thanks for the help! Back to the drawing board.

Well, after calling std::advance, you've got an iterator that has advanced as far as you wanted it to advance. What can you now do with that iterator?

F_Shit_Fitzgerald
Feb 2, 2017



VikingofRock posted:

Well, after calling std::advance, you've got an iterator that has advanced as far as you wanted it to advance. What can you now do with that iterator?

I actually figured it out, thanks to your help and Stack Exchange.

This code probably won't win any design awards, but it's functional:

code:
std::list<customClass*>::const_iterator it = dataList.begin();
for (int foo = 0; foo < i; ++foo) {
   ++it;
}

return *it;
What this does is iterate a non-pointer variable, foo, the same number of "spaces" as the iterator. Then it simply returns the iterator at the spot where it left off in the loop.

VikingofRock
Aug 24, 2008




F_Shit_Fitzgerald posted:

I actually figured it out, thanks to your help and Stack Exchange.

This code probably won't win any design awards, but it's functional:

code:
std::list<customClass*>::const_iterator it = dataList.begin();
for (int foo = 0; foo < i; ++foo) {
   ++it;
}

return *it;
What this does is iterate a non-pointer variable, foo, the same number of "spaces" as the iterator. Then it simply returns the iterator at the spot where it left off in the loop.

Yup, you got it! The only other thing that I was trying to hint at there was that your for loop is equivalent to your call to std::advance. So you can do

C++ code:
const customClass* getValue(unsigned int i) const {
    auto it = dataList.cbegin();
    std::advance(it, i);
    return *it;
}
edit: You might also want to consider what to do in the case that i is greater than the length of the list, depending on whether that is in the scope of the assignment.

VikingofRock fucked around with this message at 07:48 on Sep 26, 2017

F_Shit_Fitzgerald
Feb 2, 2017



VikingofRock posted:

Yup, you got it! The only other thing that I was trying to hint at there was that your for loop is equivalent to your call to std::advance. So you can do

C++ code:
const customClass* getValue(unsigned int i) const {
    auto it = dataList.cbegin();
    std::advance(it, i);
    return *it;
}
edit: You might also want to consider what to do in the case that i is greater than the length of the list, depending on whether that is in the scope of the assignment.

Ohh! That makes sense. I guess I just haven't been understanding iterators quite as well as I thought. I might rewrite the loop this way, since I have a feeling my prof will be happier with this version than the somewhat clunkier version I wrote.

Thank you all for the help! You helped me figure this out without just giving me the answer, which is exactly what I needed/wanted.

F_Shit_Fitzgerald
Feb 2, 2017



I don't mean to turn this thread into my own personal homework help desk, but I'm absolutely at a loss for what to do with the one thing left to do in this assignment.

In the original code, my professor wrote a lambda function that uses std::sort to arrange the dynamic array in ascending order:

code:
std::sort(theArray, theArray + theTotal, [](const customClass& a, const customClass& b) -> bool {
		if (a.getTotal() == b.getTotal())
		{
			return a.getTotal() < b.getTotal();
		}
		else
		{
			return a.getTotal() > b.getTotal();
		}
	});
Thinking that this would be much easier with iterators, I changed the above code thusly:

code:
    std::list<customClass*>::const_iterator start = theList.begin();   
    std::list<customClass*>::const_iterator stop = theList.end();     
    
    std::sort(start, stop, [](const customClass& a, const customClass& b) -> bool {     
		.
                .
It doesn't work. When I try to compile this, it points an error to stl_algo.h and says "no match for 'operator-' (operand types are 'std::List_const_iterator<customClass*> and 'std::List_const_iterator<customClass*>'

...and points to this line in stl_algo.h:

code:
      if (__first != __last)
	{
	  std::__introsort_loop(__first, __last,
       [b]std::__lg(__last - __first) * 2, __comp);[/b]
	  std::__final_insertion_sort(__first, __last, __comp);
	}
I hate to keep asking for help, but I don't understand what's going on here.

Edit: It was late and I was tired when I wrote this.

F_Shit_Fitzgerald fucked around with this message at 07:38 on Sep 27, 2017

b0lt
Apr 29, 2005

F_Shit_Fitzgerald posted:

uses std::sort to arrange the dynamic array in ascending order:

std::list isn't a dynamic array, it's a linked list.

F_Shit_Fitzgerald posted:

because the list contains a combination of strings and floats, I'm not sure it'd behave properly.

what

F_Shit_Fitzgerald
Feb 2, 2017



b0lt posted:

std::list isn't a dynamic array, it's a linked list.


what

Right. The assignment is to convert all instances of dynamic arrays to using standard lists.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah, std::sort requires random-access iterators. I don't know what your professor is asking here; presumably not that you rewrite std::sort or hack the iterator type to pretend to be random-access when it isn't.

Xarn
Jun 26, 2015
Or use std::list::sort.

Also that lambda body doesnt look quite right.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

F_Shit_Fitzgerald posted:

code:

    std::list<customClass*>::const_iterator start = theList.begin();   
    std::list<customClass*>::const_iterator stop = theList.end();     
    
    std::sort(start, stop, [](const customClass& a, const customClass& b) -> bool {     
		.
                .

It doesn't work. When I try to compile this, it points an error to stl_algo.h and says "no match for 'operator-' (operand types are 'std::List_const_iterator<customClass*> and 'std::List_const_iterator<customClass*>'
Your list contains pointers, the lambda takes references/objects.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I'm making a geometry system, and as part of that I have a static polygon class whose vertices and edges are known at compile time. For cache purposes I want to make a templated class that takes number of vertices and number of edges, so that all geometry data is continuous in memory. However, I have an issue that the virtual intersect function for static polygons on my Shape superclass is complaining about not having the template arguments. Also, I'm not actually sure how to provide the vertices through an initializer list to the constructor.

My shape class:
C++ code:
class Shape2D {
public:
    virtual bool inline intersects(const PolygonStatic2D& poly2)=0;
};
The static polygon class:
C++ code:
template<uint32_t vertexCount, uint32_t edgeCount>
class PolygonStatic2D : public Shape2D {
public:
    PolygonStatic2D(const glm::vec2 vertices[vertexCount], const glm::ivec2 edges[edgeCount]) {
        memcpy(this->vertices, vertices, vertexCount * sizeof(glm::vec2));
        memcpy(this->edges, edges, edgeCount * sizeof(glm::ivec2));
    }
...
}
Where I'm trying to initialise a static polygon superclass through the initialiser list:
C++ code:
class Rect : public PolygonStatic2D<4,4> {
public:
    Rect(glm::vec2 dimensions) :
            PolygonStatic2D<4,4>(
                    {
                        glm::vec2(),
                        glm::vec2(),
                        glm::vec2(),
                        glm::vec2()
                    },
                    {
                        glm::ivec2(),
                        glm::ivec2(),
                        glm::ivec2(),
                        glm::ivec2()
                    })
    {

    }
};
Is there a fairly graceful solution to any of these issues?

Joda fucked around with this message at 17:56 on Sep 27, 2017

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
If your primary use for this type is dynamic in the number of vertices, you’re not really getting anything by templating it, because you’ll have to do something to reintroduce that dynamicism.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Oh right. I also just realized that the offset between the two arrays won't be known by the compiler if it has to treat them as the same object type. I guess I'll just go with vectors for now and revisit this if it proves unperformant. Thanks.

VikingofRock
Aug 24, 2008




So I've got a question on linking on OS X, which I hope falls under the purview of this thread. I'm trying to get an executable to correctly link to a library in an unusual location (I'm pretty sure the version available in homebrew has a bug which I am trying to track down, so I can submit a patch). Currently I am linking with the command

code:
c++ -o foo foo.o -rpath /path/to/my/version/of/library/ -L /path/to/my/version/of/library/ -lCCfits
where /path/to/my/version/of/library/ contains the a standard stuff emitted by make: libCCfits.0.0.0.dylib, libCCfits.0.0.0.dylib-master.o, libCCfits.0.dylib, libCCfits.dylib, libCCfits.la, and libCCfits.lai. However, when I run otool -L foo, I get that it is trying to link to "/usr/local/lib/libCCfits.0.dylib (compatibility version 1.0.0, current version 1.0.0)", which doesn't exist anymore (that was the homebrew version which I uninstalled). So what gives? Am I messing up the linking command somehow? Or is there some other problem?

y_y
Oct 25, 2011

conversationalist

VikingofRock posted:

So I've got a question on linking on OS X, which I hope falls under the purview of this thread. I'm trying to get an executable to correctly link to a library in an unusual location (I'm pretty sure the version available in homebrew has a bug which I am trying to track down, so I can submit a patch). Currently I am linking with the command

code:
c++ -o foo foo.o -rpath /path/to/my/version/of/library/ -L /path/to/my/version/of/library/ -lCCfits
where /path/to/my/version/of/library/ contains the a standard stuff emitted by make: libCCfits.0.0.0.dylib, libCCfits.0.0.0.dylib-master.o, libCCfits.0.dylib, libCCfits.dylib, libCCfits.la, and libCCfits.lai. However, when I run otool -L foo, I get that it is trying to link to "/usr/local/lib/libCCfits.0.dylib (compatibility version 1.0.0, current version 1.0.0)", which doesn't exist anymore (that was the homebrew version which I uninstalled). So what gives? Am I messing up the linking command somehow? Or is there some other problem?

I don't know what's going wrong in your case, but install_name_tool allows you to modify those paths after the fact (which is also helpful if you want to include .dylibs in your .app-bundle).

VikingofRock
Aug 24, 2008




y_y posted:

I don't know what's going wrong in your case, but install_name_tool allows you to modify those paths after the fact (which is also helpful if you want to include .dylibs in your .app-bundle).

Thanks, this is helpful to know for the future. For this case I ended up just adding a temporary symlink in /use/local/lib/ while I was debugging things.

baby puzzle
Jun 3, 2011

I'll Sequence your Storm.
If my program crashes on somebody's machine, I want it to log the callstack, and create a crash dump file.

I'm using this StackWalker library, which appears to do what it says on the tin, as far as generating a callstack. But how do I catch a crash? Of course, I have no idea where my program is going to crash, so I'm wrapping the entirety of main() in a __try/__except block, just like the example given:

code:
// The exception filter function:
LONG WINAPI ExpFilter(EXCEPTION_POINTERS* pExp, DWORD dwExpCode)
{
    StackWalker sw;
    sw.ShowCallstack(GetCurrentThread(), pExp-&gt;ContextRecord);
    return EXCEPTION_EXECUTE_HANDLER;
}

// This is how to catch an exception:
__try
{
    // do some ugly stuff...
}
__except (ExpFilter(GetExceptionInformation(), GetExceptionCode()))
{
}
But it doesn't build when I try to use t he __try/__except:

1>c:\users\dwlem\documents\mymusic\mymusic.cpp(7592): error C2712: Cannot use __try in functions that require object unwinding

My main() is about 1000 lines of random poo poo that I'm trying to encapsulate in the block. Is this the right way to catch a crash? I don't know what to do with this error, nor do I have any idea how exceptions work.

baby puzzle
Jun 3, 2011

I'll Sequence your Storm.
Oh, the solution is to literally move my code elsewhere and do this:

code:
int main( int argc, char* argv[] )
{
	__try
	{
		return fakemain( argc, argv );
	}
	// end of __try
	__except (ExpFilter(GetExceptionInformation(), GetExceptionCode()))
	{
	}
}
That makes no loving sense to me, but whatever. I don't care now.

Doc Block
Apr 15, 2003
Fun Shoe
It looks like __try is some non-standard Microsoft thing. Like they bolted exceptions onto C.

MrMoo
Sep 14, 2000

Windows has SEH exceptions in addition to C++ ones, __try __catch is for the SEH ones.

ullerrm
Dec 31, 2012

Oh, the network slogan is true -- "watch FOX and be damned for all eternity!"

Doc Block posted:

It looks like __try is some non-standard Microsoft thing. Like they bolted exceptions onto C.

Correct — he’s doing Win32 “structured exception handling” which is the OS-level debugging facility for doing poo poo in response to process-ending conditions. Segfaults, illegal instructions, uncaught C++ exceptions, etc all pass through this system before the big exit().

baby puzzle posted:

Oh, the solution is to literally move my code elsewhere and do this:

That makes no loving sense to me, but whatever. I don't care now.

The short version is that you can’t mix C++ exceptions and SEH exceptions in a top-level SEH block, because it’s not sure what objects need to get their destructors run. When it’s in a helper function, the compiler can say “okay I know I need to unroll all objects up to this function call boundary.”

Also, fwiw, doing crash handling in-process is really unreliable, because its not guaranteed if you have the CRT state / free memory / unmolested stack to do a bunch of poo poo in the same process right after catching the exception. I’d strongly suggest using a watcher thread with preallocated space to do this, or better yet, a separate watcher process. Check out the Breakpad library, which is used for crash reporting for both Firefox and Chrome (and untold other products).

baby puzzle
Jun 3, 2011

I'll Sequence your Storm.

ullerrm posted:

Also, fwiw, doing crash handling in-process is really unreliable, because its not guaranteed if you have the CRT state / free memory / unmolested stack to do a bunch of poo poo in the same process right after catching the exception. I’d strongly suggest using a watcher thread with preallocated space to do this, or better yet, a separate watcher process. Check out the Breakpad library, which is used for crash reporting for both Firefox and Chrome (and untold other products).

How would you handle a crash outside of the process? That doesn't even make any sense to me. Can one thread or process watch for a crash in another?

Breakpad looks like overkill and I don't think I could ever get it working anyway.

vote_no
Nov 22, 2005

The rush is on.
I feel like replacing "// do some ugly stuff" with one's entire program is a good indicator that something is wrong. C++ Core Guidelines E.17 and E.18 come to mind. To be fair, I've never tried to do the whole "send information about this crash to the developers" thing but I can't imagine that a whole-program try/catch could ever be a sensible method of going about it.

baby puzzle
Jun 3, 2011

I'll Sequence your Storm.
I don't know any better? There isn't supposed to be any exceptional behavior happening anywhere in my code, anyway.

The guidelines aren't useful: "Let an exception propagate until it reaches a function that can handle it." Ok, well, none of my code is handling any exceptions at all.

e: I guess I could follow that guideline, if I had the foresight to know where my program might unexpectedly... But.. that's stupid.

baby puzzle fucked around with this message at 03:05 on Oct 19, 2017

Adbot
ADBOT LOVES YOU

Doc Block
Apr 15, 2003
Fun Shoe
You don’t know which parts of your code might generate exceptions or what those exceptions are likely to be?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply