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
c0burn
Sep 2, 2003

The KKKing
I love how with topics like C, compilers etc even in 2016 you can't beat a good book. K&R is still the one.

Adbot
ADBOT LOVES YOU

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Do people still like Muchnick as a compiler book?

Sex Bumbo
Aug 14, 2004

c0burn posted:

I love how with topics like C, compilers etc even in 2016 you can't beat a good book. K&R is still the one.

Once you decide to use the internet for something (like putting a book on it) all you care about is javascript :(.

Chuu
Sep 11, 2004

Grimey Drawer
I'm trying to write to a binary protocol that has ~100 different types of messages. Luckily the vendor gave me a .h file that contains one POD struct per message type so you can access the relevant fields just by just overlaying the correct struct onto your buffer.

The correct struct being discovered by a massive switch statement over a common header all messages share.

Is there an external tool that can take all these POD objects and generate methods to pretty print them for debugging?

Top Bunk Wanker
Jan 31, 2005

Top Trump Anger

c0burn posted:

I love how with topics like C, compilers etc even in 2016 you can't beat a good book. K&R is still the one.

You ever try to solve a single C or C++ problem with Google? It's virtually impossible to find an actual answer to anything that isn't extreme beginner stuff, and even then you have five or guys all waggling their dicks about exactly what the right way to solve the problem is.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Top Bunk Wanker posted:

You ever try to solve a single C or C++ problem with Google? It's virtually impossible to find an actual answer to anything that isn't extreme beginner stuff, and even then you have five or guys all waggling their dicks about exactly what the right way to solve the problem is.
That's what you get in your own head when you're an experienced programmer too, so ...
(Though at least when it's all yourself it's easy to get into a rhythm of just always trusting the guy who says use boost, or always trusting the guy who says STL, or always trusting the guy who says gently caress that noise do everything C-style, so you get to skip the analysis paralysis.)

dougdrums
Feb 25, 2005
CLIENT REQUESTED ELECTRONIC FUNDING RECEIPT (FUNDS NOW)
I have "Engineering a Compiler" by Cooper and Torczon, a good deal of it is on google books: https://books.google.com/books?id=_tgh4bgQ6PAC&lpg=PP1&pg=PP1#v=onepage&q&f=false

I wrote a compiler while reading it, so I'd say it's useful. Everything feels real organized, and it makes a superb reference text. It can read a little weird in some places but it's not opaque. I didn't know about optimizing other than "make a dag", but I was able to glean a lot of good stuff and now my programs go fast(er). I'd recommend it, but I don't know how useful you would find it for your purposes.

feedmegin
Jul 30, 2008

Subjunctive posted:

Do people still like Muchnick as a compiler book?

I do (as an advanced 'how do I optimise poo poo' text, not like compilers 101).

I'm kind of curious how much of it is relevant to the modern day, though - these days I would have thought optimising memory accesses, cacheing and so on is way way more important than the sort of micro-optimisations traditional compiler spent a lot of effort on.

Edit: I liked Linkers and Loaders, but it is very specifically about linkers and loaders so unless you're going to be directly messing about with PE-COFF/Mach-O/ELF files you're going to get limited use out of it (and if you are doing that it's useful background but you could probably just read the relevant spec for the file format you're interested in instead).

feedmegin fucked around with this message at 13:36 on Mar 24, 2016

Hubis
May 18, 2003

Boy, I wish we had one of those doomsday machines...

feedmegin posted:

I do (as an advanced 'how do I optimise poo poo' text, not like compilers 101).

I'm kind of curious how much of it is relevant to the modern day, though - these days I would have thought optimising memory accesses, cacheing and so on is way way more important than the sort of micro-optimisations traditional compiler spent a lot of effort on.

Edit: I liked Linkers and Loaders, but it is very specifically about linkers and loaders so unless you're going to be directly messing about with PE-COFF/Mach-O/ELF files you're going to get limited use out of it (and if you are doing that it's useful background but you could probably just read the relevant spec for the file format you're interested in instead).

I gather that caches are way bigger, deeper, and more sophisticated these days and so (a) the added functionality makes some of those optimizations necessary and (b) the added complexity makes lower level optimizations harder so you focus on higher level "general behavior" instead.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Memory optimizations are certainly very important, but there are also a lot of important non-memory optimizations (e.g. devirtualization and inlining), and it's not like those micro-optimizations are no longer valuable at all.

Sex Bumbo
Aug 14, 2004
Wouldn't those both fall under memory optimizations in a way?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Sex Bumbo posted:

Wouldn't those both fall under memory optimizations in a way?

Not under any useful classification, no. If you're going to go :catdrugs: on me, then registers are just a kind of memory, so maybe everything is a memory optimization. Usually, though, a memory optimization is focused on optimizing program-visible memory, like store propagation or dead store elimination, not just literally anything that might change how many raw memory accesses are performed, like inlining or register allocation.

vileness fats
Sep 16, 2003

College Slice
Late to the party, but in general the Intel arch optimization guide is free and a good place to start (depending on platform). It's perfectly readable even if you don't write much asm.

Xarn
Jun 26, 2015
What do I need to find out and replicate in a VM, to be able to precompile .o files in a VM that will link properly when used on the real machine?

I already know that it is running Debian Jessie, is using g++ 4.9.2 and should be able to find out anything else I will need to.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

Xarn posted:

What do I need to find out and replicate in a VM, to be able to precompile .o files in a VM that will link properly when used on the real machine?

I already know that it is running Debian Jessie, is using g++ 4.9.2 and should be able to find out anything else I will need to.
Make sure you're building against headers for versions of your dependencies which are ABI-compatible between the two machines. The easiest way to do this is of course by using exactly the same versions of everything.

pseudorandom name
May 6, 2007

Why aren't you doing the final link in the VM?

Also, ABI-compatible isn't sufficient for glibc, the version of glibc that the relocatable objects were built against needs to be identical to the version that they're finally linked against.

Xarn
Jun 26, 2015

pseudorandom name posted:

Why aren't you doing the final link in the VM?

Also, ABI-compatible isn't sufficient for glibc, the version of glibc that the relocatable objects were built against needs to be identical to the version that they're finally linked against.

Because the whole thing is crazy ...


Basically, my university has a system for uploading of student's semestral work/homeworks, etc. Bolted on top of it is a system for automatic grading -- i.e. for programming classes you upload your implementation of $homework and it then gives you a grade (points for the final grade). So, this semester I decided to go and help modernize and teach our C++ course and one of the things we decided to do is to have a lot of smallish homeworks that are automatically graded.

To be nice to the students, we are using Catch for behavior tests (and we also do some more behind-the-scenes validation for correctness, i.e. use Valgrind) and give them the tests, so they can have a quicker feedback cycle than uploading it through the web interface, waiting for results and so on. However, Catch's main takes quite a long time to compile (g++ on my notebook takes 8.5s, on the server it needs 10+) and to keep the time it takes to validate student's submission short, we want to precompile it (and precompile everything else we can, while we are at it).

The fun part is, I am not allowed SSH access to the grading server (because of technical debt and lots of bureaucracy, long story), but we already got this much working -- we just had to bother someone who is allowed access to copy over a file and compile it into .o file once a week. This worked until last week, when we asked for a C++14 compiler and were told to set the grading system to use different server (the automatic evaluation system has a master server, which takes care of accepting submissions, copying it to a shared folder and farming out the actual work to different slave servers), which has different software configuration.

As we weren't able to get someone with access to this server to help us with precompiling stuff, we decided to create a VM that would allows us to create compatible .o files and then copy them to the server we have access to, because the course's folder is automagically shared with the server doing the actual evaluating.

---edit---

And no, I cannot change the evaluation script to copy back the .o files, because the moment evaluation starts, the shared folder is read-only.

Xarn fucked around with this message at 20:14 on Mar 26, 2016

Volguus
Mar 3, 2009

Xarn posted:

Because the whole thing is crazy ...
...

No, that's not crazy, that's loving insane.

Xarn
Jun 26, 2015

Volguus posted:

No, that's not crazy, that's loving insane.

And thats even without the dumb bugs I found in the ~4 weeks I am working with the system. :v:

Well at least next semester the big "rewrite" will be done. The rewrite will bolt on access control (using faculty hosted gitlab) for uploading evaluation scripts, the lovely backend will stay. :suicide:

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


I'm having a brainfart. In a file read loop using fstream where you're not reading in the loop condition, is there a 'canonical' way to check for end of file besides fstream::eof()? That only works if you tried to read past eof already, and my reader is ending precisely after reading the last byte.

Just try to seek forward 1 at the start of the loop, check eof, and seek back if you're okay? That sounds gross.

C++ code:
ifstream infile("/path/to/file.dat");
while (infile.eof() == false)
{
   unsigned char buf[256]; //arbitrarily large
   infile.read((char*)buf, 2); // record header size
   unsigned short size = buf[0] + (buf[1] << 8);

   infile.read((char*)buf, size); // record header
   // more reading
   // ...
   // if this was the last record, we're at EOF, but we haven't tried to read past it so .eof() == false
}
(ed) I guess I could change it so that first read is in the conditional and just break on eof()==true, but that feels a bit icky too.

(ed again) Nevermind, forgot about .peek(); just changed the conditional to infile.eof() == false && infile.peek() != EOF) and all was well again.

Ciaphas fucked around with this message at 00:55 on Mar 30, 2016

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop
How do you setup an environment where --sanitize=memory works? I.E., I need a completely parallel set of libraries that only get linked in my test program, since the last thing I want is system-wide libc having memory tooling enabled.

Is clang msan even production-ready? When the documentation says "To get the most of this, you should recompile the libraries you use" they really mean "The first time you use anything from STL your program will explode if you link to the system libstdc++."

I'd like to give it a shot since I found asan so useful.

Edit: And a big thanks to the "you should use rr" someone posted earlier, that's a nice addition to my toolbox.

Harik fucked around with this message at 13:54 on Apr 4, 2016

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The sanitizers generally work by instrumenting the code that gets recompiled, and they will generally only find bugs in that code; you should not need to recompile your entire library stack. I would assume that there has been some actual thought put into problems like "this uninstrumented code allocates and initializes some memory that instrumented code then accesses", but if you're running into a lot of false positives, maybe there needs to be more work put into squashing common instances of that.

Most of the C++ standard library actually gets compiled into your program and thus instrumented, so that would be a surprising source of problems.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
The documentation explicitly says "It is critical that you should build all the code in your program (including libraries it uses, in particular, C++ standard library) with MemorySanitizer" and it then goes on to give instructions on how to build and use a msan-instrumented libc++, so it should not be surprising that things do not work when using system libstdc++.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Plorkyeran posted:

The documentation explicitly says "It is critical that you should build all the code in your program (including libraries it uses, in particular, C++ standard library) with MemorySanitizer" and it then goes on to give instructions on how to build and use a msan-instrumented libc++, so it should not be surprising that things do not work when using system libstdc++.

Ah. Well, that's an unfortunate restriction.

Xarn
Jun 26, 2015
My fight with the system for automatic evaluation continues. I have given up on creating a link-compatible VM, because the target has moved and some changes in the way our own script works makes it impractical right now (if there was an easy way to get the precompiled .o files, we would would make them work, but right now :effort:). But I have new question:

Is there a way to get Valgrind working with compressed debug data? Currently it spits out a whole ton of
code:
--4273-- WARNING: Serious error when reading debug info
--4273-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
--4273-- Ignoring non-Dwarf2/3/4 block in .debug_info
which is annoying. Luckily, as far as I can see this only hits libc, libm and ld, which should mean that the user's code should still have nice stack traces, but I would prefer to solve the problem properly (ie not by filtering out these lines).

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

Harik posted:

How do you setup an environment where --sanitize=memory works? I.E., I need a completely parallel set of libraries that only get linked in my test program, since the last thing I want is system-wide libc having memory tooling enabled.
It's a big hammer, but I really like using Nix to set up reproducible build environments independent of the host system (and eachother). You should be able to install it on just about anything other than windows, and then you set up an environment like this

default.nix in your project dir:
pre:
with import <nixpkgs> {};
{ my-dev-env = stdenv.mkDerivation rec {
    name = "my-dev-env";
    version = "0.0";
    buildInputs = [ cmake libuv libpng freetype SDL2 epoxy pkgconfig ];
  };
}
and enter it from that directory with
pre:
$ nix-shell .
Note that mixing nix and host system dependencies doesn't generally work.
(adapted from the wiki)

Modifying the build process of existing packages to get features like msan set will take a bit more work but is fully supported.

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop

rjmccall posted:

The sanitizers generally work by instrumenting the code that gets recompiled, and they will generally only find bugs in that code; you should not need to recompile your entire library stack. I would assume that there has been some actual thought put into problems like "this uninstrumented code allocates and initializes some memory that instrumented code then accesses", but if you're running into a lot of false positives, maybe there needs to be more work put into squashing common instances of that.

Most of the C++ standard library actually gets compiled into your program and thus instrumented, so that would be a surprising source of problems.

Yeah. About that.

code:
int main() {
    std::map<int,int> foo;

    foo[1] = 1;
    foo[2] = 2;
    return 0;
}
explodes.

Plorkyeran posted:

The documentation explicitly says "It is critical that you should build all the code in your program (including libraries it uses, in particular, C++ standard library) with MemorySanitizer" and it then goes on to give instructions on how to build and use a msan-instrumented libc++, so it should not be surprising that things do not work when using system libstdc++.

Googling for that exact quote found the information. It's not actually in the clang documentation, but hidden away in the github wiki, which is linked with "More information" from the actual documentation. This absolutely critical tidbit of information then comes after "Using Memory Sanitizer", which does not mention that you also have to do further work for it to function at all, then Origins tracking and finally Symbolization.

Even then it directs you to a separate page! For "You must absolutely do this for this feature to work at all" it's pretty buried.

The documentation is also pretty misleading:

quote:

Full MemorySanitizer instrumentation is very difficult to achieve. To make it easier, MemorySanitizer runtime library includes 70+ interceptors for the most common libc functions. They make it possible to run MemorySanitizer-instrumented programs linked with uninstrumented libc. For example, the authors were able to bootstrap MemorySanitizer-instrumented Clang compiler by linking it with self-built instrumented libc++ (as a replacement for libstdc++).

That's just a mishmash of do-I/don't-I which muddles the issue.

Official docs posted:

Supported Platforms:
MemorySanitizer is supported on Linux x86_64/MIPS64/AArch64.

github wiki posted:

At this time, MemorySanitizer supports Linux x86_64 only.
Note that the obviously outdated documentation is the only bit that actually explains how to use it.

Kind of a mess. I don't know if anyone here is directly involved in the documentation, but my recommendation would be:

A) nuke the documentation in github, leaving the algorithm and theories there. Having separate documentation like that has led to obvious disjoints between the two sources.

B) clearly put "absolutely must rebuild every library to use this, no exceptions" with a link on how to achieve that at the top of the llvm.org documentation for the feature. "may cause false positives" is weasel wording - you absolutely will blow up the instant you use data from any non-instrumented library.

Ralith posted:

It's a big hammer, but I really like using Nix to set up reproducible build environments independent of the host system (and eachother).

I should do that. I've got three targets - amd64, arm-linux and arm-android-linux, and it while the builds are automatic the scripting is custom and somewhat fragile.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
It sounds like msan is only minimally production-ready, then.

Le0
Mar 18, 2009

Rotten investigator!
I wanna play with Qt and I'd like to make an application that can handle data packets (ethernet, ip or whatever).
I'm thinking of creating each packet field as a std::bitset, then concatenate all the bitset to create the complete packet.

Would there be a better type suited to do this?

feedmegin
Jul 30, 2008

Le0 posted:

I wanna play with Qt and I'd like to make an application that can handle data packets (ethernet, ip or whatever).
I'm thinking of creating each packet field as a std::bitset, then concatenate all the bitset to create the complete packet.

Would there be a better type suited to do this?

That seems like it would be...slow.

The old-school way would be to use pointers of the relevant type and offset (uint32_t's or whatever) into a buffer. Watch for network versus host byte order! (because unless you're on a SPARC box like it's 1995 or something else old-school, those will be different).

eth0.n
Jun 1, 2012

Le0 posted:

I wanna play with Qt and I'd like to make an application that can handle data packets (ethernet, ip or whatever).
I'm thinking of creating each packet field as a std::bitset, then concatenate all the bitset to create the complete packet.

Would there be a better type suited to do this?

I assume you're doing this as a personal challenge? Otherwise, you should be using higher level libraries for network communication, or a library like libpcap if you want to deal with low level packet details.

With that assumption, sure, std::bitset is a fine way to handle the flag fields, but it would be silly to use it for the numerical fields.

@feedmegin: shouldn't be so bad. It's an extra copy vs manipulating in place, but bitsets themselves are no slower than manual bit-fiddling, assuming the bitset fits in a primitive integral type.

b0lt
Apr 29, 2005

feedmegin posted:

The old-school way would be to use pointers of the relevant type and offset (uint32_t's or whatever) into a buffer. Watch for network versus host byte order! (because unless you're on a SPARC box like it's 1995 or something else old-school, those will be different).

Endianness doesn't matter much anymore, everything that matters is little endian (except for fields that are mandated to be big endian :argh:). If you care about endianness, you should be using a library that handles things for you (protobuf, capn proto, or whatever), because it's super easy to omit a swizzle operation that doesn't get noticed until someone actually uses your code on a big endian system.

eth0.n posted:

With that assumption, sure, std::bitset is a fine way to handle the flag fields, but it would be silly to use it for the numerical fields.

Bit fields are better, it lets you name your bits and allocate multiple bits to a field more easily.

eth0.n
Jun 1, 2012

b0lt posted:

Bit fields are better, it lets you name your bits and allocate multiple bits to a field more easily.

But the bit representation of bit fields is non-portable. This means if you, for example, have a set of 32 flags packed into a 32-bit integer, with a bitset, you can gain portable (assuming endianness is handled) bitwise access with a single integral copy. With bit-fields, the only portable way to do it is 32 individual bit extractions and writes to a bit-field, because the compiler can put the bit fields in any arbitrary order.

Bit fields are OK for data structures that live solely in the memory of a given computer, but for network programming, they're largely a trap. The traditional "correct" way to do it is with manual masking and shifting; std::bitset is a nice C++ abstraction for doing that.

eth0.n fucked around with this message at 19:40 on Apr 5, 2016

feedmegin
Jul 30, 2008

b0lt posted:

Endianness doesn't matter much anymore, everything that matters is little endian (except for fields that are mandated to be big endian :argh:).

Yes, that's exactly my point. The BSD sockets API and TCP/IP were both defined on big-endian machines and popularised by Sun. It's all big-endian, that's why there's ntohs and htons and whatever all over the place if you're doing low-level socket code.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

Harik posted:

I should do that. I've got three targets - amd64, arm-linux and arm-android-linux, and it while the builds are automatic the scripting is custom and somewhat fragile.
I've never actually played with the cross-compilation support, though I understand that it exists. Post your results if you have a go at it!

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop

rjmccall posted:

It sounds like msan is only minimally production-ready, then.

Seems like a theme with the llvm project. Libc++, a library supposedly designed from the ground-up around c++11, can't be used with -std=c++11.

echo '#include <string>' | clang-3.8 -c -std=c++11 -stdlib=libc++ -x c++ -
code:
In file included from <stdin>:1:
/usr/include/c++/v1/string:1938:44: error: 'basic_string<_CharT, _Traits, _Allocator>' is missing exception specification
      'noexcept(is_nothrow_copy_constructible<allocator_type>::value)'
basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
                                           ^
/usr/include/c++/v1/string:1326:40: note: previous declaration is here
    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
                                       ^
1 error generated.
I mean, it's a trivial fix (paste the NOEXCEPT specification from 1326 to 1938) but jesus christ on a pogostick how is this even possible? It specifically triggers when you use -std=c++11 or 14!

The only thing I can think of is that the compiler wasn't handling noexcept() at all in 3.7, just treating it as whitespace. Now in 3.8 it actually pays attention and fails?

Edit: It's obviously fixed already in trunk, but how did multiple releases happen where it was completely broken? Do they not dogfood it or something?

Edit2: I'm not bitching too loud, because the LLVM project is lightyears better than what GCC was, and forced it to actually do some modernization. We're all better off for it. I just work with it enough that some of the sharp edges get frustrating after a while, and it could use a dedicated polish team.

Harik fucked around with this message at 04:09 on Apr 6, 2016

sarehu
Apr 20, 2007

(call/cc call/cc)

b0lt posted:

because it's super easy to omit a swizzle operation that doesn't get noticed until someone actually uses your code on a big endian system.

You can derisk this, when rolling your own, by making wrapper types that hold the appropriate endianness or whatever, and ideally don't make it easy to serialize native int types. Also the wrapper type can be alignof=1.

pseudorandom name
May 6, 2007

__attribute__((scalar_storage_order("big-endian")))

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Harik posted:

Seems like a theme with the llvm project. Libc++, a library supposedly designed from the ground-up around c++11, can't be used with -std=c++11.

echo '#include <string>' | clang-3.8 -c -std=c++11 -stdlib=libc++ -x c++ -
code:

In file included from <stdin>:1:
/usr/include/c++/v1/string:1938:44: error: 'basic_string<_CharT, _Traits, _Allocator>' is missing exception specification
      'noexcept(is_nothrow_copy_constructible<allocator_type>::value)'
basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
                                           ^
/usr/include/c++/v1/string:1326:40: note: previous declaration is here
    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
                                       ^
1 error generated.

I mean, it's a trivial fix (paste the NOEXCEPT specification from 1326 to 1938) but jesus christ on a pogostick how is this even possible? It specifically triggers when you use -std=c++11 or 14!

The only thing I can think of is that the compiler wasn't handling noexcept() at all in 3.7, just treating it as whitespace. Now in 3.8 it actually pays attention and fails?

No, the semantic treatment of noexcept changed in a recent standards proposal, and it was probably implemented in a way that accidentally affected C++11. And MSan is an experimental technology that's been implemented on all of one platform. But, y'know, don't let that stop you from making wild-rear end general accusations about a project with hundreds of contributors.

Adbot
ADBOT LOVES YOU

Doc Block
Apr 15, 2003
Fun Shoe
:munch:

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