Sign in to follow this  

c++ new throws exception, no idea why

This topic is 4131 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

Hi, i am having a problem with new. I am calling 'new' many times a second and at some point it throws an exception. I got no idea why. I call: char *_type=new char[l+1]; The value of l is 4 or something like that. And the exception is thrown in __sbh_alloc_block(int):
    //  change size of free entry (front and back)
    if (sizeNewFree != 0)
    {
        pEntry->sizeFront = sizeNewFree;
        ((PENTRYEND)((char *)pEntry + sizeNewFree -
-->                 sizeof(ENTRYEND)))->sizeBack = sizeNewFree;
    }
The value of sizeNewFree is 20367508, memory usage looks fine in task manager (so no giant memory leaks) and i 'delete' all i 'new' when i don't need it any more. So i guess it's not free memory that's the problem. I tried catching the exception but when it's thrown once it keeps getting throwed so that didn't fix anything. Two things that might matter: I am using MSVC++ 6.0. I use multiple threads that all use new and delete extensively. Any help would be great! If you need any more info please ask.

Share this post


Link to post
Share on other sites
What exception is thrown? And what's the contents of .what()?

Quote:
I am calling 'new' many times a second and at some point it throws an exception.

How many times? Are we talking 100s or millions?

Quote:
i 'delete' all i 'new' when i don't need it any more.

Is there some point where you call new many times before deleting, if so, then how many times approximatly.

Quote:
I am using MSVC++ 6.0.
I use multiple threads that all use new and delete extensively.

I don't have access to MSVC++ 6.0 myself, so I can't check this, but are you sure new is thread-safe? If new have any static variables, and no locks, then there is a good chance you are experiencing a race condition.

Share this post


Link to post
Share on other sites
I don't know what the thrown exception is, any idea how i can find that out using the debugger or using catch(...)?
edit: It's an Access Violation exception:
First-chance exception in server.exe: 0xC0000005: Access Violation.

Quote:
Original post by CTar
What exception is thrown? And what's the contents of .what()?

Isn't .what() just for Java? If not, how can i use it when i use catch(...)?

Quote:
How many times? Are we talking 100s or millions?

Hundreds.

Quote:
Is there some point where you call new many times before deleting, if so, then how many times approximatly.

No, maybe 3 threads at the same time calling new 3 or 4 times before deleting it again.

Quote:
I don't have access to MSVC++ 6.0 myself, so I can't check this, but are you sure new is thread-safe?

I assumed it is (many programs these days use multiple threads) but i am starting to doubt it.

Share this post


Link to post
Share on other sites
The most likely cause is that you've got heap corruption somewhere in your program that causes bad things to happen when the small block handler goes to allocate a new block.

Share this post


Link to post
Share on other sites
Quote:
Original post by Tree Penguin
Isn't .what() just for Java? If not, how can i use it when i use catch(...)?

No, every class inherited from std::exception should have a .what() member.


Quote:
I assumed it is (many programs these days use multiple threads) but i am starting to doubt it.

Yes many programs these days use threads, but not many programs at the time of VC6 used threads. That program is older than the first C++ standard (1998, the second was published in 2003 and we now have technical revisions). This could very well be the source of your problem.

Share this post


Link to post
Share on other sites
Quote:
Original post by Tree Penguin
I don't know what the thrown exception is, any idea how i can find that out using the debugger or using catch(...)?
edit: It's an Access Violation exception:
First-chance exception in server.exe: 0xC0000005: Access Violation.


It's worth noting that this is not a C++ exception. Access Violations, like Division by Zero, fall under the category of SEH exceptions, and are not part of the C++ standard and thus not portable to rely on being able to handle. As far as I know, one usually has to take special steps (involving compiling a specially patched version of your compiler) to handle these on OS X/Linux. It's far easier to treat them as bugs, since they represent avoidable error conditions, and 99% of the time, indicate you're doing stuff that surely wasn't what you'd intended.

(SuperPig's Introduction to Debugging is a good starting point for this kind of thing)

Quote:
Quote:
I don't have access to MSVC++ 6.0 myself, so I can't check this, but are you sure new is thread-safe?

I assumed it is (many programs these days use multiple threads) but i am starting to doubt it.


As has been already mentioned, VS6 is positively ancient. In this train of thought, Visual Studio 2005 Express is available for free from Microsoft, and is far less ancient. I highly recommend trying it out (just make sure you follow the instructions carefully, there's post-installer installation steps that need to be followed).

Share this post


Link to post
Share on other sites
It turns out to be the multiple threads problem.
For now i fixed it by using new only at places where it's really neccessery and i use a 'notbusynewing' flag, looping the threads that want to use new until it's true, which signales the first thread that sees it is the next one in line.

It's one of the ugliest things i've done in a long time but it's an emergency fix and it works.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
There are thread safe new instances out there. Also, seriously upgrade to the FREE .NET 2005. VC6 is buggy and non-complaint, it will bite you in the butt, sooner rather then later.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
There are thread safe new instances out there. Also, seriously upgrade to the FREE .NET 2005.

I know, got no time to switch right now.

Quote:
VC6 is buggy and non-complaint, it will bite you in the butt, sooner rather then later.

I have used it for a few years now and the only real problem i faced is the problem i just discussed.

Share this post


Link to post
Share on other sites
Quote:
Original post by Tree Penguin
It turns out to be the multiple threads problem.
For now i fixed it by using new only at places where it's really neccessery and i use a 'notbusynewing' flag, looping the threads that want to use new until it's true, which signales the first thread that sees it is the next one in line.

It's one of the ugliest things i've done in a long time but it's an emergency fix and it works.
If what you've done looks something like this:
if (notbusynewing)
{
notbusynewing = false;
myPtrVar = new int[1000]; // or whatever
notbusynewing = true;
}
Then you have just shifted problem. Consider what happens when you switch threads after the code goes into the 'if' statement group, but has not yet reached that 'notbusynewing = false;' line. Another thread can then do the same thing.
For some ideas of how to get aroung this: Clicky

Share this post


Link to post
Share on other sites
Quote:
Original post by Tree Penguin
I don't know what the thrown exception is, any idea how i can find that out using the debugger or using catch(...)?
edit: It's an Access Violation exception:
First-chance exception in server.exe: 0xC0000005: Access Violation.


That's not an exception in the sense that we usually mean. That is, it isn't one that you could try/catch.

Quote:
Quote:
Original post by CTar
What exception is thrown? And what's the contents of .what()?

Isn't .what() just for Java? If not, how can i use it when i use catch(...)?


Not only is .what() not just for Java, it's *not* for Java. :)

If it *were* an exception that could be thrown, you would catch it like this:


try {
// stuff
} catch (std::runtime_error& ex) {
std::cout << ex.what() << std::endl;
}


It's usual in C++ to catch exception objects by reference, unless you're using a library that expects you to do otherwise.

If your problem were an exception of this sort, then the exception thrown by new would be of type 'std::bad_alloc', which is derived from std::runtime_error. If I'm remembering correctly, anyway (which I'm probably not).

However, your error happens because of some kind of corruption of the data that's doing book-keeping on memory. It's likely that you overwrote the bounds of one of those char arrays that you are allocating manually.

By the way, manual allocation is frequently uncalled for in C++. And allocting arrays of *chars* makes me suspicious that you might be trying to use them for string data, which would make me really sad.

Quote:
Quote:
Is there some point where you call new many times before deleting, if so, then how many times approximatly.

No, maybe 3 threads at the same time calling new 3 or 4 times before deleting it again.


That smells a *lot* like one thread tries to write to an array, expecting it to have been already resized by another thread, but getting to it before the resize happened (race condition).

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
If what you've done looks something like this:
if (notbusynewing)
{
notbusynewing = false;
myPtrVar = new int[1000]; // or whatever
notbusynewing = true;
}
Then you have just shifted problem. Consider what happens when you switch threads after the code goes into the 'if' statement group, but has not yet reached that 'notbusynewing = false;' line. Another thread can then do the same thing.

I learned at college that compilers use a cpu instruction that checks and sets a boolean in one cpu cycle with code like this, and so far that indeed seems to be the case as i did not have the problem since i used that code (even with many threads).

I'll look at the link you gave me anyway, thanks.

@Zahlman:

About .what(), sorry my bad.

About the 0xC0000005 exception, i thought that all exceptions existed to be thrown when an error occurs and catched by the program so the program can continue like normal (as in java afaik). Didn't know that it was different for exceptions like this.

Quote:
However, your error happens because of some kind of corruption of the data that's doing book-keeping on memory.

That is probably the case, if it's my arrays that have their boundaries overwritten it's because the memory for it wasn't allocated at all (because of the multiple thread problem), it's either that or it's the book-keeping data itself that gets corrupted. As i already said it works fine as long only one thread uses new, so i can't think of any other explanation.

About the char array: no, it's not a string, it contains bytes of binary data. I should probably use (unsigned) __int8 or BYTE (which also is (unsigned) char) instead to make that clear.

Quote:
By the way, manual allocation is frequently uncalled for in C++.

Why is that? Anyway, i only use new when i need an array or object that can be passed on through out the program.

Share this post


Link to post
Share on other sites
Quote:
Original post by Tree Penguin
I learned at college that compilers use a cpu instruction that checks and sets a boolean in one cpu cycle with code like this, and so far that indeed seems to be the case as i did not have the problem since i used that code (even with many threads).

While you can test and set a value atomically (though not in one instruction to my knowledge) I think it's unlikely your compiler produces code like this by default. I would use a mutex - this is after all why they exist.

Quote:
Original post by Tree Penguin
Why is that? Anyway, i only use new when i need an array or object that can be passed on through out the program.


Because manual allocation is subject to bugs time consuming to write and as you have discovered not necessarily thread safe. The C++ standard library provides std::vector which provides an array that takes care of all that for you

Share this post


Link to post
Share on other sites
Quote:
Original post by chowe6685
While you can test and set a value atomically (though not in one instruction to my knowledge) I think it's unlikely your compiler produces code like this by default.


Yes, in one CPU instruction (there are several that are suitable on the x86). That's why it can be atomic. [smile]

Share this post


Link to post
Share on other sites
I've always implemented a test and set using something like


mov eax, 0x1
xchg eax, memoryaddress
test eax



of these only xchg is guaranteed to be atomic and it's only a part of the test and set operation

Is there a better way?

Share this post


Link to post
Share on other sites

This topic is 4131 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this