Jump to content
  • Advertisement
Sign in to follow this  
i_luv_cplusplus

Crash in debug, works in release?

This topic is 3556 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Recently I tried to learn templates and I wanted to put them to use writing a very simple memory manager (wrappers on new and delete, actually). I met a strange behaviour of STL string I cannot explain logically. Consider these two pieces of code:
#include <iostream>
#include <string>

class MemoryManager
{
  public:
    MemoryManager(){}
    ~MemoryManager(){}
    template <class allocType> void allocate(allocType* _data, unsigned int _size, std::string _source)
    {
        _data = new allocType[_size];
    };
};

MemoryManager memman;

int main()
{
  float* i;
  memman.allocate<float>(i,1,"test");
  *i = 5;   // crash here
  std::cout << *i;
  return 0;
};

and a second one, with different function arguments
#include <iostream>
#include <string>

class MemoryManager
{
  public:
    MemoryManager(){}
    ~MemoryManager(){}
    template <class allocType> void allocate(allocType* _data, unsigned int _size)
    {
        _data = new allocType[_size];
    };
};

MemoryManager memman;

int main()
{
  float* i;
  memman.allocate<float>(i,1);
  *i = 5;
  std::cout << *i;
  return 0;
};

Now, the second code works flawlessly. On the other hand, the first one crashes in debug mode and works fine in release. Does anyone have an idea what's going on? I don't even USE the passed string, it must be STL doing something to me :( By the way, I am using Code::Blocks and MinGW.

Share this post


Link to post
Share on other sites
Advertisement
I think you should try this test:

int main()
{
float* i;
std::cout << "initial value of i " << i << '\n';
memman.allocate<float>(i,1);
std::cout << "allocated value of i " << i << '\n';
};


Share this post


Link to post
Share on other sites
i is a pointer. You don't initialize it, so it holds nothing. When you send him to the function allocate, a new pointer name _data is created. Any changes made to the pointer _data will not affect the pointer i. Changes to the data referred by the pointer _data will affect the data referred by the pointer i, since they refer to the same data - as long as you don't change the pointer _data before you change the data it refers.

That means that if you allocate some memory and put a reference to it in the pointer _data, the pointer i will not change. It will still point to the same place in memory it pointed before. Therefore, calling the function allocate has no effect('cept leaking memory, ofcourse).


Change the function's title to this:
template <class allocType> void allocate(allocType* &_data, unsigned int _size, std::string _source)

Notice the '&'? That will send the pointer by reference, and any changes to the pointer _data will affect the pointer i.

Share this post


Link to post
Share on other sites
That fixed it.
Still, I don't understand why it works in release mode without the &.
I tried this:


std::cout << "value before: " << *i << "\n";
memman.allocate<float>(i,1,"test");
*i = 1673;
std::cout << "value after: " << *i << "\n";



and it gives me:

Quote:

value before: 5.95133e-039
value after: 1673


if the data isn't allocated, I shouldn't be able to change it? Does that mean that I'm changing an undefined location in memory and it's just the release build mode that doesn't check access violations?

Share this post


Link to post
Share on other sites
Quote:
Original post by i_luv_cplusplus
if the data isn't allocated, I shouldn't be able to change it? Does that mean that I'm changing an undefined location in memory and it's just the release build mode that doesn't check access violations?


You got it!

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy
Quote:
Original post by i_luv_cplusplus
if the data isn't allocated, I shouldn't be able to change it? Does that mean that I'm changing an undefined location in memory and it's just the release build mode that doesn't check access violations?


You got it!


Not quite. Access violations are checked by the OS so running in Release or Debug mode doesn't change anything.

What is actually happening is that running in Debug mode will cause non-active memory to be filled with certain patterns. For uninitialised memory will be set to a particular value. These values are highly likely to cause access violations if interpreted as an address. In release mode the values could be anything, including addresses that are valid inside the processes address space.


Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Quote:
Original post by someboddy
Quote:
Original post by i_luv_cplusplus
if the data isn't allocated, I shouldn't be able to change it? Does that mean that I'm changing an undefined location in memory and it's just the release build mode that doesn't check access violations?


You got it!


Not quite. Access violations are checked by the OS so running in Release or Debug mode doesn't change anything.

What is actually happening is that running in Debug mode will cause non-active memory to be filled with certain patterns. For uninitialised memory will be set to a particular value. These values are highly likely to cause access violations if interpreted as an address. In release mode the values could be anything, including addresses that are valid inside the processes address space.


Yup! When I get a crash in debug or not release or vice-versa, I tend to start looking for the memory patterns. Once you've been programming for a while, when you see CDCDCDCD as a pointer and you try to dereference it, you'll instantly say "Doh!"

Obviously, differences between debug and release are much more than that. Hell, a few days ago a professor showed us a case where the VS2003 compiler generated the wrong code when it was in release (due to an error in their optimization). It was actually the first time I've seen a crash, not because of incorrect code written by the programmer, but bad code by the compiler! That story is for another thread though.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!