PDA

View Full Version : Program works while debugging with debug or release mode, but an executable alone not



mamannon
01-05-2017, 01:09 PM
Hello folks,

I have really weird dilemma: I have Win32 CAD program, whose OpenGL related DLL library is compiled by a Visual Studio 2010 and other parts of program are compiled dy Embarcadero XE8. The whole system works fine on three separate workstations when debugging it with Visual Studio 2010, but if I try to run the executable alone, some test files (not every file) doesn't show lightning, dark world or at least distorted static shadows shows up instead.

So, with debugger everything is working perfectly, but executable alone only part of the test files works as expected. And more confusion, if I first open a perfectly working file and then a file which doesn't show lightning, then both files are working perfectly or at least lights are on but shadows may be off. However, this misbehaviour is deterministic: it does always the same fails and same order even on different machines. Nvidia or AMD don't make a difference with regard to their behaviour or misbehaviour. GeForce GT 525M, AMD Radeon R6 and GeForce GTX 860M show equal behaviour.

What could be wrong?

1: I think this could be some out-of-memory problem. The program doesn't check available memory on board and it doesn't count the memory needed to load some file, but after loading more OpenGL stuff it checks GL_OUT_OF_MEMORY by glGetError(). But, because I get the lightning working by loading a file after another, this doesn't seem a memory problem (the first file is still loaded, so there is more OpenGL stuff on board). Anyway, opengl driver memory management is tricky -actually I dont know, I only guess- so if the driver feels it doesn't have enough memory or time, is it possible that driver just silently refuses to allocate space or transfer data and keep working like everything was okay?

2: On the other way, it is possible that CUDA or OpenCL could indirectly cause a lightning problem, but I don't delieve it because the behaviour is identical between a CUDA machine and an OpenCL machine. If the problem would be there, their behaviour would differ. Moreover, the case where lights are on but shadows are absent or distorted, is definitely not a CUDA or OpenCL case. But if you think I should double check or triple check CUDA/OpenCL, I'm glad if you tell it to me.

3: The third sympton would be threads: I use boost::thread and boost::asio libraries to handle four threads, and OpenGL rendering context is connected to two of them, in different times I hope. This is the thing I suspect at most. But, if this is the reason of misbehaviour, shouldn't it prevent rendering completely? All rendering is happening in a same thread, which calls a single render function that draws everything. Moreover, the program works either with OpenGL 4.0 or OpenGL 1.5, and they both use the same threading skeme. OpenGL 1.5 works perfectly with all files, so this is an indication that threads work correctly.

4: Some other reason you name it :)

Please help, any suggestions are welcome...

mamannon
01-11-2017, 05:18 AM
There were bugs here and there, but one thing I want to point out: If you are using boost threads and OpenGL, make sure that OpenGL thread is always bound the thread which "talks" with OpenGL. If there are several threads talking to OpenGL, you need to change context between threads by wglMakeCurrent:



wglMakeCurrent(NULL, NULL); //leaving thread

wglMakeCurrent(Window_Handle/HDC, Rendering_Handle/HGLRC); //new thread


Context changing is an expensive operation as well as to create and destroy threads. Therefore I'm using boost::asio library which keeps your threads alive, so a single thread invocation and destruction happens during the lifetime of a program. There is one caveat about boost::asio and OpenGL: DON'T USE A THREADPOOL!! If you do that, you're forced to call wglMakeCurrent every time you use your threads. Instead use fixed threads and call wglMakeCurrent only once. Below is an example class how to do that:



#ifndef __saie_H
#define __saie_H

class Saie : public boost::asio::io_service::service {

private:
boost::asio::io_service ioPalvelu;
boost::shared_ptr<boost::asio::io_service::work> tyo;
boost::shared_ptr<boost::thread> saie;
volatile bool sammutus;

Saie(const Saie& saie);
Saie & operator=(const Saie& saie);

public:
Saie(boost::asio::io_service& io);
virtual ~Saie();

//we need to define an abstract method
void shutdown_service() {}

//returns a reference to this service
boost::asio::io_service& annaPalvelu();

//test whether the service is ready
bool onkoPysaytetty();

//run a thread
void saieRun(void (*funktio)());

//stop service
void saieStop();

//restart service
void saieReset();
};

#endif




#include "stdafx.h"

#include "saie.h"

Saie::Saie(boost::asio::io_service& io) : boost::asio::io_service::service(io),
ioPalvelu(),
tyo(new boost::asio::io_service::work(ioPalvelu)),
saie(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioPalvelu))) {

sammutus=false;
}

Saie::~Saie() {
saieStop();
}


boost::asio::io_service& Saie::annaPalvelu() {
return ioPalvelu;
}

bool Saie::onkoPysaytetty() {
return sammutus;
}

void Saie::saieRun(void (*funktio)()) {
ioPalvelu.post(funktio);
}

void Saie::saieStop() {
if (sammutus==false) {
ioPalvelu.stop();
if (saie) {
saie->join();
}
sammutus=true;
}
}

void Saie::saieReset() {
if (sammutus==true) {
ioPalvelu.reset();
tyo.reset(new boost::asio::io_service::work(ioPalvelu));
saie.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioPalvelu)));
sammutus=false;
}
}