Re: String Appender Fails (Memory Allocation Failure)

2011-07-14 Thread Loopback

Anybody got an idea?


Re: String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread Loopback

On 2011-07-14 01:11, Loopback wrote:

Hello!

I've been working on a project where I had to do all memory handling
explicitly because no destructors were called. When I got too tired
of the explicit memory handling I decided to trace what was causing
this error. After hours of code stripping I had gotten myself a
small concrete sample which could demonstrate the error.

Now to the point; I create a program using WinMain as entry point. The
program template i use, is identical to the win32 template on the
D-Website. If you have used this template you know that all user code
goes within the function myWinMain. In this function I declare a class
named Foo. When I create this class an empty constructor is called, and
then the function myWinMain returns.

Now the program calls Runtime.terminate, which is supposed to take
care of the memory garbage and etc. This does not work. The terminate
function call throws an Error, Memory Allocation Failure.
This failure originates in the 'Foo' destructor, which in turn creates
a appender object of type string. My question is; how come this throws
an error?

Not to forget the important part:

// Import WINAPI
import win32.windows;

// Core API
import core.runtime;

// For appender
import std.range;

extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE 
hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{
int result;
void exceptionHandler(Throwable e) { throw e; }

try
{
Runtime.initialize(exceptionHandler);
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);
Runtime.terminate(exceptionHandler);
}

// If you use Exception object instead here, the program fails
	// silently without any MessageBox of any kind. The program, in this 
case quits

// automatically after about 7-12 seconds, without any destructors 
called.
// If you instead use Error object to catch the error, a message pops
// up saying, Memory Allocation Failure, why?
catch (/*Exception*/Error o) // catch any uncaught exceptions
{
		MessageBoxA(null, cast(char *) o.toString(), Error, MB_OK | 
MB_ICONEXCLAMATION);

result = 0;// failed
}

return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR 
lpCmdLine, int nCmdShow)

{
Foo foo = new Foo;
return (foo !is null);
}

class Foo
{
public:
this()
{
}

~this()
{
// This line causes memory allocation failure
auto writer = appender!string();
}
}


String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread Loopback

Hello!

I've been working on a project where I had to do all memory handling
explicitly because no destructors were called. When I got too tired
of the explicit memory handling I decided to trace what was causing
this error. After hours of code stripping I had gotten myself a
small concrete sample which could demonstrate the error.

Now to the point; I create a program using WinMain as entry point. The
program template i use, is identical to the win32 template on the
D-Website. If you have used this template you know that all user code
goes within the function myWinMain. In this function I declare a class
named Foo. When I create this class an empty constructor is called, and
then the function myWinMain returns.

Now the program calls Runtime.terminate, which is supposed to take
care of the memory garbage and etc. This does not work. The terminate
function call throws an Error, Memory Allocation Failure.
This failure originates in the 'Foo' destructor, which in turn creates
a appender object of type string. My question is; how come this throws
an error?


Re: String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread David Nadlinger

On 7/14/11 1:11 AM, Loopback wrote:

Now the program calls Runtime.terminate, which is supposed to take
care of the memory garbage and etc. This does not work. The terminate
function call throws an Error, Memory Allocation Failure.
This failure originates in the 'Foo' destructor, which in turn creates
a appender object of type string. My question is; how come this throws
an error?


Currently, no memory can be allocated at all during garbage collection 
runs, which is where destructors are usually called.


David


Re: String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread Loopback

On 2011-07-14 01:17, David Nadlinger wrote:

Currently, no memory can be allocated at all during garbage collection
runs, which is where destructors are usually called.

David


That explains it. Do you know when this feature will be available, if
at all?

Here is another interesting case, where I am using external libraries
(FMOD) in this case.

I have two different cases here, but they have two notable things in
common. Both use WinMain as entry point and they both originate in the
class Foo.

In the first case, I use the class Foo, which has the Sound
class as a private member. If foo omits the call to allocate the sound
class no Memory Allocation Failure occurs. This error is also avoided
if the two lines in the static destructor of sound is omitted:

FMOD_System_Close(m_system);
FMOD_System_Release(m_system);

How come these external functions generates a Memory Allocation Failure
when they use malloc for their memory allocation? Also worth noticing
is that in the non-static destructor FMOD_Sound_Release is called
without any problems, if the two function calls are omitted.

One other thing; how come no Memory Allocation Failure occurs, when
I do not allocate the sound class, since the static de-/constructors
of the class are still called?

In the second case, the exact same functions are called except that
everything takes place in-lined in the Foo constructor.

Case 1: Memory Allocation Failure and Sound destructor is not called.
Case 2: Everything works as expected.
// Import WINAPI
import win32.windows;

// Core API
import core.runtime;

import std.range;
import std.string;

// FMOD
import fmod.fmod;

extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPSTR lpCmdLine, int nCmdShow)
{
int result;
void exceptionHandler(Throwable e) { throw e; }

try
{
Runtime.initialize(exceptionHandler);
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);
Runtime.terminate(exceptionHandler);
}

catch (Error o)
{
MessageBoxA(null, cast(char *) o.toString(), Error, MB_OK | 
MB_ICONEXCLAMATION);
result = 0;// failed
}

return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, 
int nCmdShow)
{
Foo foo = new Foo;
return (foo !is null);
}

class Foo
{
public:
this()
{
//m_sound = new Sound(rC:\acdc.ogg);
}

~this()
{
MessageBoxA(null, Never Called, Error, MB_OK | 
MB_ICONEXCLAMATION);
}
private:
Sound m_sound;
}

class Sound
{
public:
static this()
{
if(FMOD_System_Create(m_system) != FMOD_RESULT.FMOD_OK)
throw new Error(Failed to create fmod system.);

if(FMOD_System_Init(m_system, 2, FMOD_INIT_NORMAL, null) != 
FMOD_RESULT.FMOD_OK)
throw new Error(Failed to initialize fmod.);
}

static ~this()
{
// Close and release system (omitting these prevents any errors 
from occuring)
FMOD_System_Close(m_system);
FMOD_System_Release(m_system);
}

this(string file)
{
if(FMOD_System_CreateSound(m_system, cast(char *) 
file.toStringz, FMOD_HARDWARE | FMOD_LOOP_OFF, null, m_sound) != 
FMOD_RESULT.FMOD_OK)
throw new Error(Failed to create sound.);
}

~this()
{
// Release Sound
FMOD_Sound_Release(m_sound);
}

private:
static FMOD_SYSTEM * m_system;  
FMOD_SOUND * m_sound;
}// Import WINAPI
import win32.windows;

// Core API
import core.runtime;

import std.range;
import std.string;

// FMOD
import fmod.fmod;

extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPSTR lpCmdLine, int nCmdShow)
{
int result;
void exceptionHandler(Throwable e) { throw e; }

try
{
Runtime.initialize(exceptionHandler);
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);
Runtime.terminate(exceptionHandler);
}

catch (Error o)
{
MessageBoxA(null, cast(char *) o.toString(), Error, MB_OK | 
MB_ICONEXCLAMATION);
result = 0;// failed
}

return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, 
int nCmdShow)
{
Foo foo = new Foo;
return (foo !is null);
}

class Foo
{
public:
this()
{
FMOD_SYSTEM * m_system; 
FMOD_SOUND * m_sound;

if(FMOD_System_Create(m_system) != FMOD_RESULT.FMOD_OK)
throw