Here is algorithm of stack, I want to know what can be function stack-full, here? Or something like it about queue.
Procedure ADD(item,a,n,top)
if(top>=n) then stack-full()
top++;
a(top) <-- 1
end
It is an abstract handler to handle a stack overflow. You are to decide what it should do: throw an exception or increase stack size.
Related
In short, while the code seems to work fine, I'm curious of whether less hacky approaches (than the ones I came up so far) with exist.
Suppose you create a coroutine via lua_newthread, and later suspend it from a cclocure via lua_yield. Your program takes a lap around non-Lua code, and it is now time to resume the coroutine via lua_resume, but - suppose the arguments that Lua code provided are extremely illegal, and we should give it an error to indicate that.
As you might know, you can't call lua_error (or luaL_error) on a state unless it's currently running. So the state must resume but immediately get hit by an error.
In 5.3 you would use lua_yieldk, provide a continuation function, and call lua_error or luaL_error in there. Et voilĂ .
But, alas - LuaJIT does not implement lua_yieldk, so what options are we left to?
A single-use hook
Suppose the error message is stored in a char error_text[256]. We could then bind a per-instruction hook immediately before resuming,
lua_sethook(L, throw_error, LUA_MASKCOUNT, 1);
int result = lua_resume(L, NULL, ret_count);
and then unbind the hook and throw an error in there
void throw_error(lua_State *L, lua_Debug *ar) {
lua_sethook(L, throw_error, 0, 0);
if (error_text == nullptr) return; // trust no one, especially yourself
luaL_error(L, "%s", error_text);
}
Should string cleanup be required, you would of course prefer to concatenate error_text to luaL_where(L, 1) yourself before calling _error, as both lua_error and luaL_error do a long jump and thus will be the last thing your function does.
A Lua-side wrapper
Suppose you decide to pull a somewhat node.js-like on this and have your C code resume with an error, result pair so that you could have a wrapper function like so
function some(arg)
local e, r = some_native(arg)
if (e) then
error(e)
else
return r
end
end
Or maybe refactor your API entirely so that errors are also handled using the same pattern, but that's a story for another day.
Option 1 seems less hacky of two.
Option 2 seems less likely to cause any trouble.
I can't help the feeling that there's a much better way of doing this that I'm overlooking (after all, lua_yieldk is a relatively recent addition).
a lua function return two number
c++ calls the lua function: foo
I don't know whether it's needful to pop the return value of function foo(lua_pop(L,2);).
please tell me how to do it and why. thanks very much.
part code like this:
// lua function
function foo(a, b)
return a+b, a-b;
end
// c++
lua_getglobal(L,"foo"); // push function
lua_pushnumber(L,1); // push argument 1
lua_pushnumber(L,2); // push argument 2
error=lua_pcall(L, 2, 2, 0);
if (!error) {
printf("return:%s\n",lua_tostring(L,-1));
printf("return:%s\n",lua_tostring(L,-2));
// is this needful
lua_pop(L,2);
}
You should always try and keep the stack in a known state, in case you call more functions using the same lua_State. If you leave results sitting on the stack and make more calls, you will eventually fill the available stack space up.
So yes, you should pop the 2 results off the stack after using their values.
I am really confused on the concepts of:
Don't use exceptions as control flow
Don't return nil/false as an exception
Say I have the following instance method:
class Logo
# This method has some logic to create an image using Rmagick
def process
begin
#logo_image = RmagickHelper.new(self.src)
rescue Magick::ImageMagickError
raise Exceptions::LogoUnprocessable, "ImageMagick can't process the URL"
end
end
end
So in a more general method I have the following:
def build_all_images
begin
#logo.process
rescue Exceptions::LogoUnprocessable
#logo.status = 'unprocessable'
return false #This terminates the method so no more stuff is processed, because logo could not be processed.
end
#....
end
My question is:
Is this correct to do:
raise Exceptions::LogoUnprocessable, "ImageMagick can't process the URL"
Or should I have just done
return false
Once upon a time there was a language with no exception constructs (c). Each message returned an integer - 0 for success or some error-code for failure. If the caller did not check the return code before continuing - he'd be screwed. Also, most of the time the caller had nothing he could do about the failure, so even when he did check the result - the only intelligent thing he could do is return its own error code...
Then came c++, with exception constructs, just for these use-cases. Exceptions are made for times where the method got into a situation it could not handle (like reading a file that was not there, or surfing the web without internet connection).
Abusing the Exception construct means that an exception is raised in a totally expected situation, for example:
def even?
if (self % 2 != 0)
raise NumberNotEvenException
end
end
Here a number being odd is legitimate, and expected; throwing an error is misusing the exception construct.
Throw an exception when the method cannot fulfill what it promised to do.
On the flip side - returning nil or false when a method fails brings us back to the happy c days, where it is the burden of the caller to notice the failure, and figure out what went wrong - not fun.
The difference has to to do with how often the failure happens and whether it is a simple return value.
Asking "is this a valid url" would expect a "false" value, but In this case, it would seems that a when a valid url is expected, the failure case warrants an exception.
Exceptions are "exceptional" or unusual. Exceptions happen in command methods, where you are telling it to "do this" and it says "oops!"
Flow control is more of a question "what is this" in which case "oops" doesn't make sense.
Also, consider the number of times the code is called - exceptions take a lot more time to process than a simple return value.
The code says it all:
#tryModA.lua:
f,err=loadfile("tryModB.lua")
if not f then
print("F is nil!!! Err:"..err)
else
f.fn=function (x)
print("x="..x)
end
f()
end
And here is the loaded file:
#tryModB.lua:
fn("hello")
Error:
lua: tryModA.lua:7: attempt to index global 'f' (a function value)
stack traceback:
tryModA.lua:7: in main chunk
[C]: ?
Question: why does it happen ?
Isn't it true that loadfile() returns a function object and I can attach another function to it? PS. I come from a JavaScript programming background where it has prototype-based objects. I assume Lua has the same prototype based objects.
In Lua, loadfile() returns a function (not a function object) and functions can only be called. "Attaching" whatever to a function like you are trying is not possible.
Now, Lua tables are completely different story and the prototype-based concepts from JavaScript probably apply to them (I'm not very familiar with JS). The simplest way to make your code work at this point is to make fn global i.e. replace f.fn = function... with fn = function... although this might not be what you want.
I've got some code that worked fine under Delphi 2007 but breaks under D2010. It involves passing in a string, converting it to a PWideChar (specifically, a WideString pointer, not a UnicodeString pointer), doing some processing, and then calling SysFreeString on it. It works fine until a blank string is passed in, then SysFreeString breaks. It calls a bunch of things that end up raising an Int 3 breakpoint inside NTDLL.DLL. Continuing past this point results in
Project raised exception class
$C0000005 with message 'access
violation at 0x7747206e: read of
address 0x539b8dba'.
Which, if you look closely, is not the standard Access Violation message.
The top of the stack trace when it hits the Int 3 looks like this:
:774e475d ; ntdll.dll
:774afad0 ; ntdll.dll
:774e5de9 ; ntdll.dll
:774a6dff ; ntdll.dll
:76fc1075 ; C:\Windows\system32\ole32.dll
:770e443a ; C:\Windows\system32\oleaut32.dll
:770e3ea3 oleaut32.SysFreeString + 0x4a
Does anyone have any idea what's going on here?
Edit (from the comments):
This isn't a WideString, though. It's
a PWideChar generated by
StringToOleStr, and there are no
double-free errors when a non-blank
string is passed in. Unfortunately, I
can't really post a code sample
because this is a third-party
component that's under copyright. (And
I can't ask them for support because
it's no longer supported. Basically,
the whole thing's one big mess.)
I'm going to try psychic debugging. You've got some kind of heap corruption in your application and SysFreeString is the unfortunate victim (it's hard to tell without OS symbols, you should probably install the MSFT symbol packages for your OS).
Try enabling application verifier (in particular pageheap) for your app and see if it crashes earlier.
It is hard to diagnose without seeing your actual code, however WideString automatically calls SysFreeString() when it goes out of scope. It sounds like your code may be making a second call to SysFreeString() on memory that has already been freed. WideString itself has not changed at all between D2007 and D2010, but other aspects of Delphi's string handling have. Maybe you are not managing the strings correctly. Can you please show your actual code?
A simple test shows that you need to be really careful on what you do in which order.
So: even though you cannot post a small example, can you indicate what you are doing in a bit more detail?
Bad debugging; ignore the things below; see comment.
The SysFreeString() is being called at the end of the the Allocate() call, even though it returns a PWideChar:
program ShowStringToOleStrBehaviourProject;
{$APPTYPE CONSOLE}
uses
SysUtils;
function Allocate(const Value: UnicodeString): PWideChar;
begin
Result := StringToOleStr(Value);
// implicit SysFreeString(WideChars);
end;
procedure Run;
var
WideChars: PWideChar;
begin
WideChars := Allocate('Foo');
Writeln(WideChars);
end;
begin
try
Run();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Note the console still outputs 'Foo' because the memory has not been overwritten yet.
--jeroen
It can be different reasons of such kind of errors:
You try to free with SysFreeString a memory which are allocated not with SysAllocString, but for example with CoTaskMemAlloc.
You have heap correct.
Heap corruptions are difficult to localize. The function HeapSetInformation can be very helpful. For example you can use
HeapSetInformation(NULL,HeapEnableTerminationOnCorruption,NULL,0);
Other good way is usage of HeapValidate function. For example you can define a function which verify all heaps pf the process (code in C, which can be easy rewritten in Delphi):
BOOL MyHeapValidate (void)
{
HANDLE hProcessHeaps[1024];
DWORD i;
DWORD dwNumberOfHeaps;
BOOL bSuccess = FALSE;
dwNumberOfHeaps = GetProcessHeaps (sizeof(hProcessHeaps)/sizeof(hProcessHeaps[0]),
hProcessHeaps);
if (dwNumberOfHeaps > sizeof(hProcessHeaps)/sizeof(hProcessHeaps[0])) {
MessageBox(NULL, TEXT("GetProcessHeaps()"),
TEXT("Error in MyHeapValidate()"), MB_OK);
return FALSE;
}
for (i=0; i<dwNumberOfHeaps; i++) {
bSuccess = HeapValidate (hProcessHeaps[i], 0, NULL);
if (!bSuccess)
return bSuccess;
}
return bSuccess;
}
The usage of this function can be like following:
void BadFunction(BSTR bstr)
{
LPOLESTR psz = OLESTR("Test12");
lstrcpy (bstr, psz);
}
int main()
{
LPOLESTR psz = OLESTR("Test");
BSTR bstr = SysAllocString (psz);
// verify that before call of BadFunction() all process heaps are OK!
if (!MyHeapValidate()) {
_tprintf(TEXT("heap is corrupted after the step 1.\n"));
return 1;
}
BadFunction(bstr);
if (!MyHeapValidate()) {
_tprintf(TEXT("heap is corrupted after the step 1.\n"));
return 1;
}
SysFreeString (bstr);
return 0;
}
With respect of inserting MyHeapValidate() in different suspected places you can very quickly local the place of corruption.
+1 for Larry Osterman's answer.
Some Windows memory functions behave slightly different under debugger: if they detect some kind of misuse - they trigger breakpoint to notify debugger. So, basically, your code is doing something wrong.
You can install hooks on SysAllocString/SysFreeString and redirect them to your memory manager (which should be in full debug mode) to collect more info. Or you can just pass these calls through to original functions, installing only a filter, which watches for memory actions.
And you can install debug symbols to get more info too (I'm not sure if Delphi debugger can use it, but Process Explorer - can. You can connect it to your process and see call stack).