I have one of the most annoying problems in my opinion, called a segmentation fault. Usually with a bit of help from gdb and tracing all my code, I manage to solve these problems. Unfortunately, not this time. Since my code is kind of complex, I will show snippets relevant to the problem.
First of all, the error is given on this setter function:
void Texture::setRenderer( SDL_Renderer* renderer ) {
m_renderer = renderer;
}
Ofcourse, in my texture class there is a variable defined as followed:
SDL_Renderer* m_renderer = nullptr;
Because of the type of error, I tried tracing the specific memory address, to see if it is valid. So, the parameter. It comes from my resource manager class, which is trying to add a texture to a map. Specific code:
bool ResourceManager::add( const std::string texture ) {
Texture* tex;
tex->setRenderer(m_renderer);
}
Ofcourse, also this variable (m_renderer) comes from a different location. My Game class.
m_resources.setRenderer(m_renderer);
This function is called immediately after I initialize the renderer, without any errors. So there my trace ends, without finding the problem...
I have also tried printing the memory address in all of these functions. They all print exactly the same memory address.
Stacktrace from gdb:
Thread 1 "ConceptGame" received signal SIGSEGV, Segmentation fault.
0x0000000000408868 in Texture::setRenderer (this=0x0, renderer=0x660b60)
at ../Texture.cpp:68
68 m_renderer = renderer;
(gdb) bt
#0 0x0000000000408868 in Texture::setRenderer (this=0x0, renderer=0x660b60)
at ../Texture.cpp:68
#1 0x0000000000406865 in ResourceManager::add (this=0x7fffffffdb50,
texture="penguin.png") at ../ResourceManager.cpp:31
#2 0x0000000000403fb1 in Game::run (this=0x7fffffffdae0) at ../Game.cpp:83
#3 0x0000000000408b5f in main (argc=1, argv=0x7fffffffdcb8) at ../main.cpp:50
Any help on fixing this problem is much appreciated...
Wow. I just solved this indeed according to AndyG's comment...
While trying to fix this I accidentally didn't initialize the pointer, thus causing this problem.
Fixed by initializing the pointer;
Texture* tex = new Texture;
tex->setRenderer(m_renderer);
Thank you.
Related
I'm trying to run a member function in a thread, but I get the error illegal operation on bound member function, I'm not sure what I'm doing wrong. I would like if someone could explain me what I'm doing wrong and why I get this error, and give me an example of how to fix it. The code looks like this:
void GameWorld::SetupWorld()
{
// create the window (remember: it's safer to create it in the main thread due to OS limitations)
RenderWindow window(VideoMode(800, 600), "OpenGL");
// deactivate its OpenGL context
window.setActive(false);
// launch the rendering thread
Thread thread(&Render, &window);//This line gives the error
thread.launch();
}
void GameWorld::Render(RenderWindow* window)
{
Texture texture;
Sprite sprite;
if (!texture.loadFromFile("sprite.png"))
{
}
sprite.setTexture(texture);
// the rendering loop
while (window->isOpen())
{
// clear the window with black color
window->clear(Color::White);
// draw everything here...
window->draw(sprite);
// end the current frame
window->display();
}
}
You have a serious case of undefined behavior from passing a pointer to a local variable to the thread.
Once the function returns, that variable will go out of scope, and the object will be destructed, leaving you with a pointer to unallocated memory.
You also have a problem if the Render function is not static, because non-static member functions have a hidden first argument that becomes the this pointer inside the member function. It's probably this problem that the compiler is complaining about.
A possible third problem might be that once the SetupWorld function returns, your thread variable will also go out of scope and be destructed. Depending on what threading framework you're using it might kill the thread quite unexpectedly.
To fix the compilation error change your complaining line to Thread thread(&GameWorld::Render, &window)
However for completeness you should read #Some programmer dude's answer.
My program crashes before main() function. I determine this using "cerr":
int main(int argc, char **argv)
{
cerr << " MAAIN " << endl;
The message from gdb:
Reading symbols for shared libraries ...........+++............................ done
CA(34652) malloc: *** error for object 0x7fff76694860: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
0x00007fff88e1782a in __kill ()
(gdb) bt
#0 0x00007fff88e1782a in __kill ()
#1 0x00007fff8c4d2a9c in abort ()
#2 0x00007fff8c53184c in free ()
#3 0x00000001026a1db0 in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow ()
(gdb)
I have checked the code for "delete" and "free" functions. All deletes are done with check like this:
if (x) delete x;
Please help me with answering two questions:
1. What can be the possible problem?
2. How to find it? (I have a big code with a lot of files and cmake for compilation).
P.S. I read Is there any way a C/C++ program can crash before main()? but looking at gdb massage I suppose libraries are ok.
cout is not a good way to check where your program is crashing because cout does not immediately flush its buffer and it is possible that you programs crashes after cout but before flushing buffer. it's better to check it with cerr instead of cout
And before main function, constructors of global variables will call. so take look at them if you think it crashes before start.
an other possibility is allocating memory for arrays in you main function that happens before calling of main function. if they are huge. you must use new to allocate memory for them.
std::basic_stringbuf<char, std::char_traits<char>... tells me that it's std::string that is going wrong. One quite possible scenario is that you have something that is trying to "free" a string, that hasn't been constructed correctly or that has been overwritten by uncareful use of arrays.
Or you are relying on some global variables in different source files, so you have something like this:
// main.cpp:
...
extern string str; // str lives in another .cpp file
....
myclass x(str); // Construction using str.
// otherfile.cpp
string str("foobar");
In this case, str may not be constructed by the time x is being constructed, and the string is "invalid".
There are oodles of other possibilities along similar lines.
The address here: 0x7fff76694860 is on the stack. If it's always the same value, you could try to track down where it is.
I'm making a simple deck/card/hand object oriented system for a university assignment, and I've become stuck on this problem.
I've set up a simple test class which calls various methods in objects.
int main() {
Deck deck = Deck();
deck.DisplayDeck();
deck.Shuffle();
deck.DisplayDeck();
Hand hand = Hand(1);
Card* card;
card = deck.DealNextCard();
hand.AddCard(card);
hand.ftring();
deck.DisplayDeck();
}
The problem comes at hand.ftring(). When I call this, it causes a segmentation fault. The weird thing is, it contains no code.
in hand.cpp:
string Hand::ftring() {
}
If I remove it, it runs to completion. If I add a console output to the method, it prints it and then crashes. I'm completely at a loss as to what to do, as the debugger only states
Program received signal SIGSEGV, Segmentation fault.
In ?? () ()
You declare that you are returning a string in ftring function, but you don't actually return anything. This is bad.
Your method must return a string - this is the way you've declared it. You're getting undefined behavior.
I have this very annoying issue, whenever i call a function:
void renderGame::renderMovingBlock(movingBlock* blockToRender){
sf::Shape blockPolygon;
sf::Shape blockLine = sf::Shape::Line(blockToRender->getLineBegin().x,blockToRender->getLineBegin().y,blockToRender->getLineEnd().x,blockToRender->getLineEnd().y, 3.f,movingBlockLineColor);
for(auto i = blockToRender->getVertexArray()->begin(); i!=blockToRender->getVertexArray()->end(); ++i){
blockPolygon.AddPoint(i->x, i->y, movingBlockBlockColor);
}
renderToWindow->Draw(blockLine);
renderToWindow->Draw(blockPolygon);
}
Which is a simple function, it takes a pointer to an object and uses SFML to render it on the screen. It's a simple polygon that moves on a rail.
getVertexArray() returns a pointer to the object's vector of vertices, renderToWindow is a pointer to sf::RenderWindow
The very weird issue i have is that i can call this function it won't return from it, VC++ breaks and points me to:
int __cdecl atexit (
_PVFV func
)
{
return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
}
I'm getting weird behavoir here, i can stop this function right before exiting by calling the Display() function and system("pause"), it'll display everything perfectly fine, but one step further and it breaks.
I'll add that i'm sending a dynamically allocated object, when i set a regular one everything's fine. It's weird, when i debug the program then the polygon and line have the right coordinates, everything displays properly, but it just can't return from the function.
If a function will not return sounds like you messed up the stack somewhere previously - this is most likely an out-of-bounds write.
Or possibly because you are ending up in atexit there could have been an uncaught exception thrown.
Either way - welcome to the joys of programming - now you have to find an error which probably happens long before your function gets stuck
You could try some tools like valgrind (if its available for windows) or some other bounds checkers.
so I'm trying to make a fade transition animation for an sf::Image in SFML, and I'm have a small problem.
When I don't comment out the function called below, I get an error at the end of main() when the images are being deconstructed saying
"Windows has triggered a breakpoint. This may be due to a corruption
of the heap."
The line this happens on contains the code GLCheck(glDeleteTextures(1, &Texture));
Why would this be happening, and why only when CreateTransition() is run?
One more note: when I comment out aray[I] = aray[0] the break doesn't occur.
I posted the function below.
void CreateTransition(sf::Image& start, sf::Image animationArray[numbImgs]){
animationArray[0] = start;
void threadFunc(void* imgArray);
sf::Thread thread(threadFunc, reinterpret_cast<void*>(animationArray));
thread.Launch();
thread.Wait(); // comment this out once I get the code working
}
void threadFunc(void* ptr){
sf::Image* aray = reinterpret_cast<sf::Image*> (ptr);
sf::Color filter(0, 0, 0, 5);
for(int I= 1; I< numbImgs; I++){
//aray[I].Copy(aray[0], 0, 0, sf::IntRect(0, 0, 0, 0), true);
aray[I] = aray[0]; // error doesn't occur when commented out
RecolorImage(aray[I], filter);
}
}
Image& Image::operator =(const Image& Other)
{
Image Temp(Other);
std::swap(myWidth, Temp.myWidth);
std::swap(myHeight, Temp.myHeight);
std::swap(myTextureWidth, Temp.myTextureWidth);
std::swap(myTextureHeight, Temp.myTextureHeight);
std::swap(myTexture, Temp.myTexture);
std::swap(myIsSmooth, Temp.myIsSmooth);
std::swap(myNeedArrayUpdate, Temp.myNeedArrayUpdate);
std::swap(myNeedTextureUpdate, Temp.myNeedTextureUpdate);
myPixels.swap(Temp.myPixels);
return *this;
}
A few things which might help you narrow down the cause:
A heap corruption rarely occurs at the point when the program crashes which makes them hard to track down. It may be related to the object at the crash point or it may have been another object/code that corrupted it.
In CreateTransition() you pass the animationArray[] by value but you then pass it into a thread procedure. The lifetime of animationArray[] ends when you return from CreateTransition() which means if the thread procedure runs after this point its void* ptr parameter will not point to a valid object. You do have a thread.Wait() in the current code but also a comment about removing it. Either pass animationArray[] by reference unless there is a specific reason not to, or create a temporary copy for the thread procedure to ensure it operates on valid objects.
Consider using a std::vector<sf::Image> instead of an array.
Make sure you understand and implement the Rule of Three for sf::image and any dependent classes (like MyPixels). Not doing this can result in double-frees, leaked memory, and heap corruption like you are seeing.
If all else fails try to duplicate the issue in a temporary test project and reduce it to the smallest amount of code possible. Eliminate members of sf::image one at a time until the problem goes away. Similarly, delete lines from CreateTransition() and other lines from the thread procedure. You'll either end up with a few very specific lines that trigger the issue or an empty project.