View Full Version : EnvInvoke("Import"), Invalid address ????
Ebobtron
10th June 2007, 19:29
Hello,
@ IanB
Thank you once more for your past help. :)
I am in need of some more. :(
From inside avsFilmCutter.
When I use EnvInvoke with “Version String” all seems well.
When I use “Import” the fan begins to change color. :confused:
AVSValue res;
AVSValue argl[1] = {file};
res = env->Invoke("Import",AVSValue(argl,1));
argl[1].~AVSValue();
res.~AVSValue();
Using res.~AVSValue() causes an exception that my system seems to handle, Fizick’s just terminates the program. Fizick’s system does not crash if I bypass the destructors, but oh the memory leak.
Continued use of Invoke() and the AVSValue destructor when handled by the system, which FilmCutter will do as a user edits and updates the video viewer with the script changes, results in an eventual AviSynth crash until FilmCutter is closed and reopened.
I most days can not tell the difference between a pointer and the end of my finger, so I am convinced it must be me. My attemps, so far, have been unable to resolve this.
WinDbg will show the exception but only when used with MS’s Application Verifier which reports.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
- <avrf:logfile xmlns:avrf="Application Verifier">
- <avrf:logSession TimeStarted="2007-06-10 : 11:36:38" PID="2040" Version="2">
- <avrf:logEntry Time="2007-06-10 : 11:36:54" LayerName="Heaps" StopCode="0x13" Severity="Error">
<avrf:message>First chance access violation for current stack trace.</avrf:message>
<avrf:parameter1>3438f34 - Invalid address causing the exception.</avrf:parameter1>
<avrf:parameter2>7c809783 - Code address executing the invalid access.</avrf:parameter2>
<avrf:parameter3>13aae4 - Exception record.</avrf:parameter3>
<avrf:parameter4>13ab00 - Context record.</avrf:parameter4>
- <avrf:stackTrace>
<avrf:trace>vrfcore!VfCoreRedirectedStopMessage+81</avrf:trace>
<avrf:trace>vfbasics!VfBasicsStopMessage+1c9</avrf:trace>
<avrf:trace>vfbasics!AVrfpCheckFirstChanceException+139</avrf:trace>
<avrf:trace>vfbasics!AVrfpVectoredExceptionHandler+18</avrf:trace>
<avrf:trace>ntdll!RtlInitializeSListHead+9dbf</avrf:trace>
<avrf:trace>ntdll!LdrAddRefDll+1c1</avrf:trace>
<avrf:trace>ntdll!KiUserExceptionDispatcher+e</avrf:trace>
<avrf:trace>filmcutter!+41701a</avrf:trace>
<avrf:trace>filmcutter!+41723f</avrf:trace>
<avrf:trace>filmcutter!+416584</avrf:trace>
<avrf:trace>filmcutter!+4388a6</avrf:trace>
<avrf:trace>filmcutter!+441b76</avrf:trace>
<avrf:trace>kernel32!RegisterWaitForInputIdle+49</avrf:trace>
</avrf:stackTrace>
</avrf:logEntry>
- <avrf:logEntry Time="2007-06-10 : 11:36:56" LayerName="Heaps" StopCode="0x13" Severity="Error">
<avrf:message>First chance access violation for current stack trace.</avrf:message>
<avrf:parameter1>3438f34 - Invalid address causing the exception.</avrf:parameter1>
<avrf:parameter2>7c809783 - Code address executing the invalid access.</avrf:parameter2>
<avrf:parameter3>139b98 - Exception record.</avrf:parameter3>
<avrf:parameter4>139bb4 - Context record.</avrf:parameter4>
- <avrf:stackTrace>
<avrf:trace>vrfcore!VfCoreRedirectedStopMessage+81</avrf:trace>
<avrf:trace>vfbasics!VfBasicsStopMessage+1c9</avrf:trace>
<avrf:trace>vfbasics!AVrfpCheckFirstChanceException+139</avrf:trace>
<avrf:trace>vfbasics!AVrfpVectoredExceptionHandler+18</avrf:trace>
<avrf:trace>ntdll!RtlInitializeSListHead+9dbf</avrf:trace>
<avrf:trace>ntdll!LdrAddRefDll+1c1</avrf:trace>
<avrf:trace>ntdll!KiUserExceptionDispatcher+e</avrf:trace>
<avrf:trace>filmcutter!+41701a</avrf:trace>
<avrf:trace>filmcutter!+444ce7</avrf:trace>
<avrf:trace>filmcutter!+4388a6</avrf:trace>
<avrf:trace>filmcutter!+441b76</avrf:trace>
<avrf:trace>kernel32!RegisterWaitForInputIdle+49</avrf:trace>
</avrf:stackTrace>
</avrf:logEntry>
</avrf:logSession>
</avrf:logfile>
:thanks:
Thanks again
IanB
11th June 2007, 00:47
1. If you want my help do not post wide. Hint: I like my browser about 900 pixels wide, for maximum ease for me to read your post please try to constrain your width to this.
2. Don't include unrendered XML as text. Either render it pretty and highlight what is pertinant or just post it as a link. Again easy to read is good.
Okay, why are you manually calling the ~AVSValue destructor, it will be called automatically when stack based instances go out of scope and when you delete heap based instances.
In the case here you manually call the destructor, then the variable goes out of scope and it gets called a 2nd time and screws the clip use count.
Ebobtron
11th June 2007, 18:55
1. If you want my help do not post wide. Hint: I like my browser about 900 pixels wide, for maximum ease for me to read your post please try to constrain your width to this.
2. Don't include unrendered XML as text. Either render it pretty and highlight what is pertinant or just post it as a link. Again easy to read is good. :( :o
In the case here you manually call the destructor, then the variable goes out of scope and it gets called a 2nd time and screws the clip use count.
I sort of figured that out, but have not been able to settle on a solution. the "sort of" meaning that I could tell a pointer was out of scope, that is what I do best with them. ;) :)
Okay, why are you manually calling the ~AVSValue destructor, it will be called automatically when stack based instances go out of scope and when you delete heap based instances.
"stack based instances, heap based instances", I am flattered that you might think I should know what that means. Beyond a recently (last night) acquired and very simple academic explanation so that I might understand what you are referring to, I am making the big shrugs here.
Why?Because the following works (has presented no trouble or problems that I can recognize)
AVSValue a; a = NULL;
AVSValue vString = env->Invoke("VersionString",AVSValue(&a,0);
StringCchCopy(blah,lstrlen(vString.AsString())+1,vString.AsString());
a.~AVSValue();
vString.~AVSValue();
/*
This has lots inside before calling the env destructor, all AVSValue objects that I call a destructor for.*/
if(env) {
env->~IScriptEnvironment();
}
Because what I do, getting the version string and the function names, seems to cause no problems I repeat the use of the destructors described in the original post, because it appeared to work until Fizick identified a crash I could not duplicate without Microsoft's Application Verifier.
Another answer for your question "why" below:
AVSValue res;
AVSValue argl[1] = {file};
PClip clip;
VideoInfo info;
res = env->Invoke("Import",AVSValue(argl,1));
argl[1].~AVSValue();
if(res.IsClip()) {
clip = res.AsClip();
info = clip->GetVideoInfo();
// collect lots of data with the info object
}
return true;
The above without destructors leaks enough memory that with repeated use consumes all the system memory before crashing.
The following code cleans up the memory leak or it would appear to, this appears to crash with repeated use also. This causes Fizick's new system to crash at the end following the "return true".
info.~VideoInfo;
clip.~PClip();
res.~AVSValue();
if(env) {
env->~IScriptEnvironment();
}
if(avisynth) {
delete avisynth;
}
return true;
The short answer to your question is :stupid: ;)
Why this is happening ??? I can only guess but I will not bother you with my guesses. I am sure it is the way I have written my reader Class. I am still not sure about what I am doing, but on the stack, on the heap, who would of thunk it. :)
:)
thanks again
Rob
Leak
11th June 2007, 19:12
Ugh... please, do yourself a favour and never, ever call a C++ destructor by hand - I'm rather surprised that this is even possible.
It will automatically be called when an object on the stack (aka "a local variable that isn't a pointer to something") goes out of scope:
void foo()
{
Object a;
if (...)
{
Object b;
...
// destructor of Object b is called here automatically
}
else
...
// destructor of Object a is called here automatically
}
or when you use delete on a pointer to an object instance you created with new (which would be "on the (memory) heap", which is where non-local objects go):
Object *a=new Object(...);
...
delete a; // destructor of Object a is called here automatically before the memory is released
Hope that clears up some misconceptions you might be having... :)
So the AVSValues will take care of themselves and instead of
if (env)
env->~IScriptEnvironment();
use
if (env)
delete env;
(also, just calling the destructor like you did is creating a memory hole here - the destructor doesn't free memory, it just does what cleaning up the object required before it's deallocated - which is done with delete...)
np: Tied + Tickled Trio - A Rocket Debris Cloud Drifts (Aelita)
IanB
12th June 2007, 00:11
@Leak,Object *a=new Object(...); // Pointer to object
...
delete a; // destructor of Object a is called here ...
@Ebobtron,
Perhaps you had better post a link to the full source, this to and fro with little snippets is frustrating and will not help you learn proper technique.
Leak
12th June 2007, 09:09
@Leak,Object *a=new Object(...); // Pointer to object
...
delete a; // destructor of Object a is called here ...
Errr... oops. :(
@Ebobtron,
Perhaps you had better post a link to the full source, this to and fro with little snippets is frustrating and will not help you learn proper technique.
Agreed.
Ebobtron
12th June 2007, 16:52
:) :) :) :) ebobtron is emoting
Some time and a few lines of typing following Leaks post hit a nerve, which makes for much improved code. Big thanks. :thanks: Leaks admonishment to not do, works.
While you two where discussing the virtues of * as opposed to * I was busy fixing (sorry it is 2007 isn't it), applying a solution to this thing and using search on my editor to not do the ~ thing anywhere.
I have sent a new build to Fizick for his opinion, fingers are crossed.
Rest of today belongs to Johanna so I beg my leave of you and express my thanks. I will update this matter and ask my follow up questions soon. As for the other matter I will address this before I leave today.
:thanks:
Rob
Ebobtron
13th June 2007, 18:41
Hello,
:)
All in all, very productive. Thank you both so very much.
// start here
if(i need to)
{
Object Main;
Object A_From_Main;
Object B_From_A_From_Main;
}
// all above is gone now
return;
Is the example above always supposed to work?. For me it works sometimes and then other times not.
// start here
if(i need to)
{
Object Main;
Object A_From_Main;
if(A_From_Main)
{
Object B_From_A_From_Main;
}
}
// all above is gone now
return;The above seems to work and is the technique used to rewrite "MyAvsReader.cpp". Would the above be the correct way even if unnecessary? Or is a case by case basis more likely. Is this that class hierarchy chapter I skipped in my book.
// start here
Object Main;
if(i need to)
{
Main = new Object;
Object A_From_Main;
if(A_From_Main)
{
Object B_From_A_From_Main;
}
}
// is all above gone now ??
// is the following required or will it delete after return ??
delete Main;
return;I should know the last answer because I have used delete outside a function when another function is done with an object allocated with new.
@LeakIScriptEnvironment * env;
env = new IScriptEnvironment;
ha, ha, ha , ha
good joke ;)
@IanBI try very hard to eliminate all my bs code before jumping the gun. I miss sometimes and waste your time, I do try not to. The time you spend helping me is very respected, I am truly grateful. Pause, incoming I shall review and comment later.
My fix used in the alpha (http://avsfilmcutter.com/alpha.html) to MyAvsReader.cpp is here
http://avsfilmcutter.com/MyAvsReader.html
As for calling the destructor, sadly not the dumbest idea I have ever had.
:thanks: :)
Leak
13th June 2007, 19:11
@Leak
IScriptEnvironment * env;
env = new IScriptEnvironment;
ha, ha, ha , ha
good joke ;)
Ummm... I can't remember using "new IScriptEnvironment" anywhere... :confused:
Anyway, CreateScriptEnvironment() might be what you're after...
np: Tied + Tickled Trio - Other Voices Other Rooms (Aelita)
Ebobtron
13th June 2007, 20:30
@ Leak
Just attempting some humor, key word is "attempting", I guess.
But the joke is on me I tried it, it doesn't work.
Is not "env" a pointer to an object. From my point of view an object is an object, good thing the compiler knows the difference. :)
I is learning.
:thanks:
Leak
13th June 2007, 21:16
@ Leak
Just attempting some humor, key word is "attempting", I guess.
Meh... I'll RMA my humour detector ASAP... :D
But the joke is on me I tried it, it doesn't work.
Is not "env" a pointer to an object. From my point of view an object is an object, good thing the compiler knows the difference. :)
Oh, an instance of IScriptEnvironment is very much an object, and an IScriptEnvironment* is very much a pointer to such an object - but due to there being no (public) constructor for IScriptEnvironment (you know, that IScriptEnvironment(...) method thingy that would have to be declared inside AviSynth.h) you can't use "new" on IScriptEnvironment, or simply use IScriptEnvironment as type for a local variable.
That's where the CreateScriptEnvironment function comes in that returns a pointer to a new IScriptEnvironment - I'm afraid AviSynth.h is the best documentation in that case...
np: Porn Sword Tobacco - Giftwrap Yourself, Slowly (New Exclusice Olympic Heights)
Ebobtron
13th June 2007, 22:15
That's where the CreateScriptEnvironment function comes in that returns a pointer to a new IScriptEnvironment - I'm afraid AviSynth.h is the best documentation in that case...Yes, this I understand
but due to there being no (public) constructor for IScriptEnvironment (you know, that IScriptEnvironment(...) method thingy that would have to be declared inside AviSynth.h)this I didn't know, so if I could understand what I read.
Baby steps
and again :thanks:
Rob
IanB
14th June 2007, 02:13
The IScriptEnvironment stuff is called an Opaque class. It is a fairly advanced C++ concept. Fundamentally you write a real class, ScriptEnvironment, in this case and you only expose little pieces of it thru a restricted Interface, IScriptEnvironment, in this case. Typical of opaque classes, there is no public Constructor method, you need some static external function to obtain the object, CreateScriptEnvironment here.
In plain C the File* is an example of "Opaque". You fopen a file and get back a pointer, but you never know (or care) what the structure pointed to actually looks like.
IanB
15th June 2007, 00:51
Okay, I think you missed the gist of the exchange between Leak and myself re * versus *. Leak fixed his example, hence my post now lacks context. The underlining was for emphasis, the * was originally missing.
In your example you have followed the same flaw.// start here
Object Main; // This is a full object
if(i need to)
{
Main = new Object; // This is wrong, Main is not a pointer
...
}
// is all above gone now ??
// is the following required or will it delete after return ??
delete Main; // This is wrong, Main is not a pointer
return;I think what you actually want to say in this example is this.// start here
Object *Main = NULL; // A pointer to Object, init to null
if(i need to)
{
Main = new Object; // Make Object on heap
Object A_From_Main; // Full object on stack
if(A_From_Main)
{
Object B_From_A_From_Main; // Full object on stack
}
}
// stack based things above gone now
if (Main) delete Main; // Remove heap object if it was created
return;The analogy from C is malloc() and free()
char string[10]; // A 10 byte string on the stack
versus
char *string = malloc(10); // A 10 byte string on the heap
...
free(string); // cleanup!
Ebobtron
15th June 2007, 08:10
Okay, I think you missed the gist of the exchange between Leak and myself re * versus *. Leak fixed his example, hence my post now lacks context. The underlining was for emphasis, the * was originally missing.And still right over my head. I undersood the emphasis but not its importance. I was hoping there was an explanation but my remark was mostly a joke, later obscured by the missing * in my question. As for the missing * I made a "dumb a" mistake which has boned the focus of the question.
I under stand simple pointers, the key word being simple, just don't always type or proofread well. And I get the new / delete thing like C's malloc() and free() (I don't know much about C either). Heap or stack, didn't know and didn't know I should care until now.
IanB
19th June 2007, 09:11
Okay who can spot the logic flaw in the following (all the error checking and try/catch removed for clarity)void routine()
{
IScriptEnvironment* env=CreateScriptEnvironment();
PClip clip = env->Invoke("Import", szScriptName).AsClip();
const VideoInfo &VI = clip->GetVideoInfo();
...
delete env;
}
Hidden text> Well it is quite subtle, PClip clip is a smart pointer. As it is on the stack the compiler runs the ~PClip() destructor when clip goes out of scope, at the last } here, after the delete env; oops the PClip destructor runs after env has been deleted. The fix is quite simple add a clip = 0; before the delete env; <Hidden text
Select between the Hidden text markers to read the answer.
Leak
19th June 2007, 09:24
Okay who can spot the logic flaw in the following (all the error checking and try/catch removed for clarity)void routine()
{
IScriptEnvironment* env=CreateScriptEnvironment();
PClip clip = env->Invoke("Import", szScriptName).AsClip();
const VideoInfo &VI = clip->GetVideoInfo();
...
delete env;
}
Gah. Just open a block before the PClip and close it before the delete. Problem solved... :p
Bidoche
19th June 2007, 15:31
What about using a smart pointer for the env too.
Then no more work or worry, the destructeurs will be run in the reverse of declaration order.
...
ie if u could do that, and if iirc correctly there is a reason it doesn't.
Groucho2004
7th July 2011, 14:23
What about using a smart pointer for the env too.
Then no more work or worry, the destructeurs will be run in the reverse of declaration order.
...
ie if u could do that, and if iirc correctly there is a reason it doesn't.
Sorry about resurrecting such an old thread but here (http://forum.doom9.org/showthread.php?p=1265812#post1265812) is a very neat solution.
Gavino
7th July 2011, 15:20
I don't really see any 'problem' to solve.
IanB and Leak have already shown the right way to do it.
Groucho2004
7th July 2011, 15:44
I don't really see any 'problem' to solve.
IanB and Leak have already shown the right way to do it.
I know, I just remembered a case where "delete env" was causing trouble (I think it was with DGDecNV).
neuron2
7th July 2011, 16:39
I know, I just remembered a case where "delete env" was causing trouble (I think it was with DGDecNV). No, it was HCEnc.
Groucho2004
7th July 2011, 16:47
No, it was HCEnc.
Ah yes, I remember. So, how does HCEnc release the IScriptEnvironment object (if at all)?
neuron2
8th July 2011, 03:53
Sorry, I lost the notes from my collaboration with Hank to fix that, and my memory is coming up blank.
From 2.6 there is now a IScriptEnvironment::DeleteScriptEnvironment() method.
This then does the "delete env" in the same CRT heap environment as the original "env = new ScriptEnvironment;"
There might be a problem if the CRT used by Avisynth.dll seriously disagrees with the CRT used by the host code. So far I have only been caught out when using debug heap tracking, I was freeing something that was never allocated by the debug heap routines, and it was right some other code had done the allocation. :o
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.