I'm trying to load several symbol modules using the following code:
DWORD64 dwBaseDllSymLocal = 0;
SymInitializeW(GetCurrentProcess(), NULL, FALSE);
SymSetOptions(SYMOPT_DEBUG);
dwBaseDllSymLocal = SymLoadModuleExW(GetCurrentProcess(), NULL, L"C:\\module1.dll", NULL, 0, 0, NULL, 0);
if (0 == dwBaseDllSymLocal)
{
__debugbreak();
}
dwBaseDllSymLocal is 10000000 now.
dwBaseDllSymLocal = SymLoadModuleExW(GetCurrentProcess(), NULL, L"C:\\module2.dll", NULL, 0, 0, NULL, 0);
if (0 == dwBaseDllSymLocal)
{
__debugbreak();
}
Dbghelp gives the following message: module1 is already loaded at 10000000.
Same behavior happens when I try to load the same module twice. (unlike what is written in the documentation of the function).
Last error is ERROR_INVALID_ADDRESS though it doesn't seem relevant, because last error has this value following the first successful function call too.
Is it possible to load several modules with SymLoadModuleExW? What is the right way to do so?
You are loading these binaries outside of the context of a debugger session, right? In which case, the fifth parameter, BaseOfDll, might be causing a problem:
The load address of the module. If the value is zero, the library obtains the load address from the symbol file.
When loading a binary standalone, it might just use 10000000 for everything... in which case, the second module load would conflict with the first one. So try passing something different there.
Last error is [...] though it doesn't seem relevant, because last error has this value following the first successful function call too.
If the function succeeds, the last error is not applicable; it could contain anything, but you should ignore it unless the documentation explicitly says that it sets the last error in success cases.
Related
I'm currently learning how to use the Lua C API and while I've had success binding functions between C/C++ and Lua, I have a few questions:
Is it a good idea to load multiple scripts into a single lua_State? Is there a way to close specific chunks? If a script is no longer in use how can I clear it from the lua_State while retaining everything else?
What is the best way use scripts that may use the same name for functions/global variables? If I load all of them the newer definitions override the older ones.
After reading online I think I need to separate each loaded chunk
into different environments. The way I envision this working is each
time a chunk is loaded I assign it a unique environment name, when I
need to work with it it I just use that name to fetch the
environment from the LUA_REGISTRYINDEX and perform the operation. So
far I haven't figured out how to do this. There are examples online
but they use Lua 5.1.
Is it a good idea to load multiple scripts into a single lua_State?
Yes, definitely. Unless those scripts is unrelated and should run in multiple parallel threads.
Is there a way to close specific chunks?
Chunk is just a value of type "function". When you don't have that value stored anywhere - chunk will be garbage-collected.Anything chunk produced - globals, or locals that has references somewhere outside - those will live on.
how to clear it from the lua_State while retaining everything else?
That depends on how do you see that chunk. Is it just a set of functions, or represents some entity with own state. If you don't create global functions and variables, then everything defined in separate script file will be local to chunk, and will be removed when there's no references to chunk left.
What is the best way use scripts that may use the same name for functions/global variables?
Consider rewriting your code. Do not create any globals, unless it's explicitly required to build communications with other parts of your program. Make variables local (owned by chunk), or store it in table/closure that will be returned by chunk as new object - chunk might be a factory producing new objects, and not jush the script.Also Lua runs just faster with local variables.
The way I envision this working is each time a chunk is loaded I assign it a unique environment name
You should do that if scripts comes from outside - written by users, or received from other external sources. Sandboxing is cool, but there's no need in sandboxing if chunks is your internal stuff. Consider rewriting code without globals. Return some object (api table, or closure) if your chunk produces other objects - you can call that chunk many times without reloading it. Or save one global - module interface, if chunk represents Lua-like module. If you don't organize your code well, then you will be forced to use separate environments, and you'll have to prepare new environment for every script, copy basic stuff like print/pairs/string/etc. You'll have many breaks in run time until you figure out what's more is missing from new environment, and so on.
After poking around some more I found what I think is the solution I was looking for. I'm not sure if this is the correct/best way to do it, but it works in my basic test case. #jpjacobs answer on this question helped a lot.
test1.lua
x = 1
function hi()
print("hi1");
print(x);
end
hi()
test2.lua
x =2
function hi()
print("hi2");
print(x);
end
hi()
main.cpp
int main(void)
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
char* file1 = "Rooms/test1.lua";
char* file2 = "Rooms/test2.lua";
//We load the file
luaL_loadfile(L, file1);
//Create _ENV tables
lua_newtable(L);
//Create metatable
lua_newtable(L);
//Get the global table
lua_getglobal(L, "_G");
lua_setfield(L, -2, "__index");
//Set global as the metatable
lua_setmetatable(L, -2);
//Push to registry with a unique name.
//I feel like these 2 steps could be merged or replaced but I'm not sure how
lua_setfield(L, LUA_REGISTRYINDEX, "test1");
//Retrieve it.
lua_getfield(L, LUA_REGISTRYINDEX, "test1");
//Set the upvalue (_ENV)
lua_setupvalue(L, 1, 1);
//Run chunks
lua_pcall(L, 0, LUA_MULTRET, 0);
//Repeat
luaL_loadfile(L, file2);
lua_newtable(L);
lua_newtable(L);
lua_getglobal(L, "_G");
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
lua_setfield(L, LUA_REGISTRYINDEX, "test2");
lua_getfield(L, LUA_REGISTRYINDEX, "test2");
lua_setupvalue(L, 1, 1);
lua_pcall(L, 0, LUA_MULTRET, 0);
//Retrieve the table containing the functions of the chunk
lua_getfield(L, LUA_REGISTRYINDEX, "test1");
//Get the function we want to call
lua_getfield(L, -1, "hi");
//Call it
lua_call(L, 0, 0);
//Repeat
lua_getfield(L, LUA_REGISTRYINDEX, "test2");
lua_getfield(L, -1, "hi");
lua_call(L, 0, 0);
lua_getfield(L, LUA_REGISTRYINDEX, "test2");
lua_getfield(L, -1, "hi");
lua_call(L, 0, 0);
lua_getfield(L, LUA_REGISTRYINDEX, "test1");
lua_getfield(L, -1, "hi");
lua_call(L, 0, 0);
lua_close(L);
}
Output:
hi1
1
hi2
2
hi1
1
hi2
2
hi2
2
hi1
1
I'm using Lua 5.3.2 with Visual Studio 2013 if that means anything.
This basic test case works as needed. I'll continue testing to see if any issues/improvements come up. If any sees any way I could improve this code or and glaring mistakes, please leave a comment.
you should treat each of your scripts as different module.
just like you have more then 1 "require" in your code.
your 'loaded chunk' should return table that will be stored globally.
this isn't good idea to load a lot of global variables, this can cause bad thing after you will add more modules.
I've a fairly simple program which needs user input in the form of a text string. I've a CLR form with an edit box and I need to take that input and pass it into my class which just copies it to a member variable.
In the Form.h code, handling the TextChanged event is...
int textLength = m_userDest->TextLength;
if (textLength > 2 && textLength < 5)
{
// Could be an ICAO code in here
char dest[5];
String^ text = m_userDest->Text->ToUpper();
sprintf_s(dest, 5, "%s", text);
airTraffic.SetUserDest(dest);
}
My class (airTraffic) SetUserDest function is just
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
When this is run I get this debug assertion, it doesn't stay on the screen and automatically clears after a few seconds.
Debug Assertion Failed!
Program: ...sual Studio 2010\Projects\FSAirTraffic\Debug\FSAirTraffic.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\tcsncpy_s.inl
Line: 24
Expression: ((_Dst)) != NULL && ((_SizeInBytes)) > 0
I don't have an f:\ drive so I'm guessing this is some internal Microsoft(?) code so I can't see the context of the assertion and exactly what it's problem is. I don't have a file called tcsncpy_s.inl on my machine.
If I don't call my class function then there's no assertion so I assumed that was the problem.
Curiously though, when stepping through the debugger the assertion occurs as I step out of the TextChanged event, with the rest of the functions operating as intended (as far as I can see).
Does anyone know what the problem is and how I can go about solving it?
I don't understand how your code works. You use m_userDest twice, first it appears to be a pointer to a structure of some sort, maybe a handle to a TextBox control:
int textLength = m_userDest->TextLength;
Later you pass it to strncpy_s, which needs a char*, not a pointer to some structure.
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
While it's possible for a structure to implicitly convert to a char*, it's not possible for a structure pointer to do so. Perhaps there's a smart pointer involved? Or you are using the same member variable name for completely different purposes in different classes1?
In any case, strncpy_s is inspecting the value of its first argument and not liking it.
1 Note that the new "wisdom" saying not to use Hungarian notation has destroyed the ability to understand this code in textual form. We don't have an IDE providing mouseover information about the data type of variables. Applications Hungarian is still a good idea in the real world, despite how many "best practices" documents decry it. Amazing how many code style documents are written from a purely theoretical basis.
I would like to know how to loop a function to open an executable program multiple times. I tried just putting system(path) and CreateProcess(Lpath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) in a while, do while, and for loop, but that only opens the program once.
Here's what the relevant code looks like right now:
for(int i=0; i<10; i++)
{
CreateProcess(L"C:\\Users\\Ben\\Documents\\Visual Studio 2010\\Projects\\RANDWritter\\Debug\\RANDWritter.exe", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
Anyone know what to do?
Before checking with GetLastError, it's always wise to see if the function you called returned an error code or not. If it just returned a success code, then the value you get from GetLastError might be bogus. So do also use BOOL createdOK = CreateProcess(...), and check for the returned value being != FALSE before calling GetLastError.
But if it's genuinely error 87 you get, then that explains: it's name is ERROR_INVALID_PARAMETER (you can look them up at MSDN's System Error Codes page). Looking at the MSDN docs for CreateProcess, you probably cannot omit the lpStartupInfo and lpProcessInformation parameters. It's also just a good idea to fill these in regardless, since they give you info on the newly created process. More so since the handles returned in the ProcessInformation must also be CloseHandle'd manually after you're done with them.
I have the following UnitTest:
[TestMethod]
public void NewGamesHaveDifferentSecretCodesTothePreviousGame()
{
var theGame = new BullsAndCows();
List<int> firstCode = new List<int>(theGame.SecretCode);
theGame.NewGame();
List<int> secondCode = new List<int>(theGame.SecretCode);
theGame.NewGame();
List<int> thirdCode = new List<int>(theGame.SecretCode);
CollectionAssert.AreNotEqual(firstCode, secondCode);
CollectionAssert.AreNotEqual(secondCode, thirdCode);
}
When I run it in Debug mode, my code passes the test, but when I run the test as normal (run mode) it does not pass. The exception thrown is:
CollectionAssert.AreNotEqual failed. (Both collection contain same elements).
Here is my code:
// constructor
public BullsAndCows()
{
Gueses = new List<Guess>();
SecretCode = generateRequiredSecretCode();
previousCodes = new Dictionary<int, List<int>>();
}
public void NewGame()
{
var theCode = generateRequiredSecretCode();
if (previousCodes.Count != 0)
{
if(!isPreviouslySeen(theCode))
{
SecretCode = theCode;
previousCodes.Add(previousCodes.Last().Key + 1, SecretCode);
}
}
else
{
SecretCode = theCode;
previousCodes.Add(0, theCode);
}
}
previousCodes is a property on the class, and its Data type is Dictionary key integer, value List of integers. SecretCode is also a property on the class, and its Data type is a List of integers
If I were to make a guess, I would say the reason is the NewGame() method is called again, whilst the first call hasn't really finished what it needs to do. As you can see, there are other methods being called from within the NewGame() method (e.g. generateRequiredSecretCode()).
When running in Debug mode, the slow pace of my pressing F10 gives sufficient time for processes to end.
But I am not really sure how to fix that, assuming I am right in my identification of the cause.
What happens to SecretCode when generateRequiredSecretCode generates a duplicate? It appears to be unhandled.
One possibility is that you are getting a duplicate, so SecretCode remain the same as its previous value. How does the generator work?
Also, you didn't show how the BullsAndCows constructor is initializing SecretCode? Is it calling NewGame?
I doubt the speed of keypresses has anything to do with it, since your test method calls the functions in turn without waiting for input. And unless generateReq... is spawning a thread, it will complete whatever it is doing before it returns.
--after update--
I see 2 bugs.
1) The very first SecretCode generated in the constructor is not added to the list of previousCodes. So the duplicate checking won't catch if the 2nd game has the same code.
2) after previousCodes is populated, you don't handle the case where you generate a duplicate. a duplicate is previouslySeen, so you don't add it to the previousCodes list, but you don't update SecretCode either, so it keeps the old value.
I'm not exactly sure why this is only showing up in release mode - but it could be a difference in the way debug mode handles the random number generator. See How to randomize in WPF. Release mode is faster, so it uses the same timestamp as seed, so it does in fact generate exactly the same sequence of digits.
If that's the case, you can fix it by making random a class property instead of creating a new one for each call to generator.
I have some code, that build up a proxy from a type. It work perfekt.
Then I have add in the setter emit code, that it has to push a isDirty bit, when it is call. This fail, why?
If I run the code without the isDirty bit, it works.
If I run the code with the isDirty bit, it works in debug, but is start the disassembly window up in visual studio.
If I run the code with the isDirty (without-debug) the program crash (not responding) but when I hit cancel, it starts working and show all de rigth data.
PropertyBuilder property = proxy.DefineProperty(propertyInfo.Name, propertyInfo.Attributes, propertyInfo.PropertyType, null);
MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual;
MethodBuilder setMethod = proxy.DefineMethod("set_" + propertyInfo.Name, attributes, typeof(void), new Type[] { propertyInfo.PropertyType });
ILGenerator setIL = setMethod.GetILGenerator();
setIL.Emit(OpCodes.Ldarg_0); // load this on the stack - where this is the type we are creating
setIL.Emit(OpCodes.Ldarg_1); // load first parameter on the stack
setIL.Emit(OpCodes.Call, propertyInfo.GetSetMethod());
{
//error here: when this is uncomment, it fails
// // set the isDirty bit
// setIL.Emit(OpCodes.Ldarg_0); // load this on the stack
// setIL.Emit(OpCodes.Ldc_I4_1, 1); // push a number on the stack
// setIL.Emit(OpCodes.Stfld, isDirtyField); // save the value on the stack in field
}
setIL.Emit(OpCodes.Ret);
property.SetSetMethod(setMethod);
I have a hard time, seeing why this fails? Need some help from the experts :)
// dennis
I'm not sure if this is your only issue, but you are using the wrong Emit overload when emitting your Ldc_I4_1 opcode. You should do either:
setIL.Emit(OpCodes.Ldc_I4_1)
or
setIL.Emit(OpCodes.Ldc_I4, 1)
The first option will result in a slightly smaller IL method body since it uses a specialized opcode, whereas the second one is not specific to the number being loaded.