-1

Note: I have already fixed this issue by using a vector of vectors instead of an array of vectors, but I'm still curious about why the program crashed by SegFault.
In my program I have to store the meshes of multiple object types (2, in this case) as floats in vectors in order to render them using OpenGL. I had decided that reading them using ifstream and storing them in an array of std::vectors would do just fine. Here's how the loading sequence looked like:

int ObjAmount=2;
char* loadloc[ObjAmount];
//loadloc stores the paths of the files that store the meshes
loadloc[0]="IntegralHead.raw":
loadloc[1]="Pearl.raw";
vector <float> model[ObjAmount];
float modelvar;
for(int i=0; i<ObjAmount; i++)
{
      ifstream modelread (loadloc[i]);
      while(modelread>>modelvar)
      model[i].push_back(modelvar);
}

And here's how passing to the buffers looks like:

unsigned int VBO2[ObjAmount], VAO2;
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
for(int i=0; i<ObjAmount; i++)
{
      glGenBuffers(1, &VBO2[i]);
      glBindBuffer(GL_ARRAY_BUFFER, VBO2[i];
      glBufferData(GL_ARRAY_BUFFER, model[i].size()*sizeof(float), &model[i][0], GL_STATIC_DRAW);
}

The program worked just fine when I didn't turn on optimizations, but it crashed by segmentation fault in a function from atioglxx.dll when turning on the -O1, -O2, -O3 or -Os, when reaching the glBufferData call.
Any idea why the crash happened?

John
  • 181
  • 9
  • 4
    You declare `ObjAmount` after you use it. Seems like this might not be your actual code. You might work on a [mcve] since it is often the code left out that is the problem. – Retired Ninja Nov 29 '19 at 20:01
  • 6
    I find it odd that `int ObjAmount=2;` declares and initializes `ObjAmount` *after* it's used in `char* loadloc[ObjAmount];`. In addition to that, it implies `ObjAmount` is not `constexpr` yet it's used as the size of an array and `char*` can't be assigned to point to a string literal. What compiler and what flag are you using that allows all this? – François Andrieux Nov 29 '19 at 20:10
  • @RetiredNinja I messed up, sorry, I've copied the code badly to my question. It was actually initialised before. Again, sorry. – John Nov 29 '19 at 21:20
  • @FrançoisAndrieux I apologise, I copied it badly, since I had to write the question from my phone, as I couldn't from my computer. – John Nov 29 '19 at 21:22
  • @John Still, the rest of the concerns expressed in my comment stand. You can't address a string literal with a `char*` and `ObjAmount` is not a constant expression. So this code is clearly being compiled by an outdated compiler or with suspicious flags, both of which should be specified. – François Andrieux Nov 29 '19 at 21:31
  • enable warnings and read them. I'm sure your compiler would warn you about VLAs being non-standard. Also, the arrays will probably take more space on the stack and if you're teetering on overflowing the stack then changing it from an array to a vector might be the difference. – PeterT Nov 29 '19 at 21:47
  • @FrançoisAndrieux Converting strings to char* does indeed generate warnings, and if I enable the `-pendantic` flag it also tells me that I shouldn't use a variable array size. But neither of them caused the problem. **As I said, the code worked after I've replaced `vector model[ObjAmount]` with `vector > model`, but I'm not exactly sure why this fixed it.** – John Nov 29 '19 at 21:54
  • Could any of your models be empty, or the files not found? How do you populate the `vector>` model? – 1201ProgramAlarm Nov 29 '19 at 23:12
  • @1201ProgramAlarm The models aren't empty, as the console writes their sizes after it loads them. As for populating vector > I'm creating a vector dummy which is added repeatedly to the vector. **It might just be a compiler bug.** – John Nov 30 '19 at 00:10
  • The problem looks like it might be UB in another unrelated part of your code. Any change could alter how UB manifests. Changing from a local array to a vector completely relocates your data which could easily cause the UB to change. Specifically, if the crash only happens with optimizations enabled, it's very likely you have UB somewhere. The place it crashes probably has nothing to do with the actual cause. – François Andrieux Nov 30 '19 at 22:13
  • @FrançoisAndrieux You may be right, but I tried to check the code to see if I had any mistakes but I couldn't find any. Maybe it's some pretty stupid mistake that just doesn't pop up in my eye. – John Nov 30 '19 at 23:49

1 Answers1

1

When you do not turn on the optimizer, the compiler (most compilers) will generate very naive code and they may even zero initialize variables they don't have to. Just to provide a better debugging experience.

As soon as you turn on the optimizer, the compiler will stop trying to do nice things just to help you debug stuff. It will do whatever it can to make your code run fast within the rules of the language and it will take any shortcuts it can and it will, very aggressively exploit Undefined Behaviour.

If your code is 100% standard compliant, you'll be fine.

If your code goes afaul of any rule of the language, the compiler will bite you and generate garbage (or, at least not what you expect). Which it is 100% allowed to.

Remember: the compiler is not required to tell you when you break language rules. It is 100% your responsibility to know all the rules and abide by them. The compiler will assume you break no rules and generate code according to that assumption. If that assumption doesn't hold; you get arbitrary garbage (and no warnings or errors).

C++ is fiendishly complicated and difficult to work with. Don't expect the compiler to help you diagnose incorrect programs.

Turning on the optimizer is often an effective way of exposing fundamentally broken code.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • I'm still confused why would using an std::vector instead of an array would fix it, though. They both have the same size. I expect that it's some messed up memory compression made by the optimized, but I'm not sure. – John Nov 29 '19 at 21:25