6

I summarized my problem to the following short program.

It causes SEGFAULT in -O3 mode only (-O2 works fine). According to gdb it happens at *f = 0 line.

#include <iostream>

void func1(int s, int t)
{
        char* buffer = new char[s + t*sizeof(float)];
        if (!buffer)
        {
            std::cout << "new failed\n";
            return;
        }
        float* f = (float*)(buffer + s);
        for (int i = 0; i < t; ++i)
        {
            *f = 0;
            //std::cout << i << std::endl; // if uncomment this line everything will work fine
            ++f;
        }
        delete [] buffer;
        std::cout << "done\n";
}

int main()
{
        int s = 31, t = 12423138;
        std::cout << s << " " << t << std::endl;
        func1(s, t);
        return 0;
}

Please let me know, what am I doing wrong?

mambo_sun
  • 509
  • 4
  • 13
  • 8
    That is a gross violation of [the strict aliasing rule](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). As for the crash it's probably because you access unaligned data. Due to the aliasing problem it might not help, but try to compile with more warnings (e.g.`-Wall -Wextra -pedantic`) and see if it tells you anything. – Some programmer dude Nov 21 '15 at 12:43
  • @JoachimPileborg I compiled this code on MSVC with -W4 -Wx, and it compiled fine. – Algirdas Preidžius Nov 21 '15 at 12:46
  • 1
    AFAIK MSVC++ never assume strict aliasing rules and doesn't make any optimisations dependent on these rules. – Minor Threat Nov 21 '15 at 13:05
  • 5
    @AlgirdasPreidžius I [compiled it with clang](http://coliru.stacked-crooked.com/a/cb5a83ec94c8089f) and it does indeed complain that *"cast from 'char *' to 'float *' increases required alignment from 1 to 4"*. – Baum mit Augen Nov 21 '15 at 13:05
  • @JoachimPileborg I compiled it with -Wall option and it didn't complain, but I'll try it with -Wextra -pedantic. Thanks for pointing out strict aliasing rule violation – mambo_sun Nov 21 '15 at 13:07
  • 2
    This is what happens when you engage in hackery. – Lightness Races in Orbit Nov 21 '15 at 13:25
  • It seems that g++ doesn't complain about anything even with `-Wall -Wextra -pedantic` options enabled. The program doesn't crash with`--no-strict-aliasing`, but what should the one do before resorting to this option? In real life, I have a file on disk, which I would like to read into a buffer first, and then interpret some binary data from the buffer – mambo_sun Nov 21 '15 at 20:39
  • I've changed the code to [this](http://coliru.stacked-crooked.com/a/735783b1e72b2f7c). Does it break strict aliasing rule? At least clang doesn't complain about alignment anymore – mambo_sun Nov 21 '15 at 20:57
  • Solutions are provided in the StackOverflow thread mentioned in the first comment, e.g. a union. – Martin Zabel Nov 21 '15 at 21:00
  • @MartinZabel Yes, I've seen that, thx, but as I understood union requires a strict message format, whereas in my case, there may be strings of variable length inside that buffer – mambo_sun Nov 21 '15 at 21:07
  • I cannot reproduce it here. But, the actual problem should be, that the compiler moves the `delete buffer[]` before the clearing loop. How this would apply to your file I/O scenario, I cannot imagine yet. – Martin Zabel Nov 21 '15 at 21:28
  • In -O3 it crashes even when that line with `delete` commented – mambo_sun Nov 21 '15 at 21:40

1 Answers1

2

The source of SEGFAULT was not solely in violation of the strict aliasing rule, as the problem persisted even with -fno-strict-aliasing flag.

It was indeed accessing unaligned memory, but not as simple as that. As modern processors, generally allow unaligned memory access and there is even not much of an overhead nowadays. I've done some benchmarking and didn't observe a big difference in algined vs unaligned read on my Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz. Also there are some very similar (and more or less recent) results in the web.

My problem was that -O3 mode enables -ftree-vectorize flag, therefore my for cycle was vectorized (as I could see using -ftree-vectorizer-verbose flag). And (AFAIU) there is no support (yet?) for unaligned memory access using vectorized instructions, so there was a runtime exception.

This article helped me out a lot in understanding theory, though it seems that today unaligned memory access is not as harmful as it was, though still tricky

mambo_sun
  • 509
  • 4
  • 13