luaL_dofile Error - c++

Error at line "luaL_dofile" and debugger doesn't show anything about error.
I can use command "luaL_dostring" but I don't know why I can't dofile.
My code is following:
const char* file = "/app_home/data/minigames/mg_hint_machine_2.lua";
ret = luaL_dofile(LS, file);
if(ret != 0){
PRINTF("Error occurs when calling luaL_dofile() Hint Machine 0x%x\n",ret);
}
else PRINT("\nDOFILE SUCCESS");
and debugger shows error in this line and "ret" still not get returned value from dofile.
If you want to see about error in debugger
02C2D304 7C21016A stdux r1,r1,r0 03 (02C2D300) REG PIPE LSU
Debugger points in this line and I can't understand it.

As an elaboration on superzilla's answer (upvote that answer rather than this one),
to get the error message your code needs to look like this:
const char* file = "/app_home/data/minigames/mg_hint_machine_2.lua";
ret = luaL_dofile(LS, file);
if(ret != 0){
PRINTF("Error occurs when calling luaL_dofile() Hint Machine 0x%x\n",ret);
PRINTF("Error: %s", lua_tostring(LS,-1));
}
else PRINT("\nDOFILE SUCCESS");
Your change (in the comments) changed the luaL_dofile to a luaL_dostring, which is why you're getting unexpected error message ( as mentioned here ).

Putting this in the body of your if statement will help us narrow down the problem:
printf("%s\\n",lua_tostring(LS,-1));
It'll tell us what Lua is reporting when it crashes.

Related

How do I improve Lua internal error messages to include line numbers?

How do I improve the error logging to include line numbers? This is for an internal error that's thrown as I'm reading a Lua file. The only error message I get is attempt to index a function value, no line number or filename.
void handleLuaError(lua_State* L, const char* msg, const char* filename) {
handleError("%s %s: %s", msg, filename, lua_tostring(luaState, -1));
lua_pop(L, 1);
luaL_traceback (L, L, msg, 2);
char* result = 0;
if (lua_isstring(L, -1)) result = strdup_s(lua_tostring(L, -1));
lua_pop(L, 1);
SPDLOG_WARN("traceback: {}", result);
}
void readLua(const char *filename) {
SPDLOG_INFO("readLua {}", filename);
if (luaL_loadfile(luaState, filename) || lua_pcall(luaState, 0, 0, 0)) {
handleLuaError(luaState, "Reading file", filename);
}
}
I tried adding luaL_traceback, as you can see, but the only message I get from luaL_traceback is stack traceback:, no actual traceback. I read that lua_pcall can trash the stack, and that I need to do some debug logging when the error happens, such as in an error handler, and not after lua_pcall has returned. Someone suggested I need to use xpcall and provide a custom error handler, but I can't find any documentation or example code on how to call xpcall in C++.
How do I set a custom error handler? Or is there a way to just tell Lua to put more info in internal errors? When I see my particular error message in other people's StackOverflow posts, the error message (attempt to index ...) shows filename and line number, so it should be possible to get filename and line number with this error.
Here's the Lua file which is causing the error:
addAchievement({
code = "AchNewCity",
name = "A New City",
text = "Welcome to NewCity. " ..
"Your first task is to " ..
"build some roads. Click " ..
"on the Transportation Tool in the " ..
"bottom left corner.",
condition = "true",
effect = "FRoadTool,FRoadStreet",
hint = ""
});
If in doubt check for example in original source code. Lua has an interpreter lua.c that does exactly what you are trying to accomplish. You are interested in msghandler, docall and report.
lua_pcall accepts an index to message handler as fourth argument. It can be used to retrieve information about error's environment and so on. After lua_pcall returns you can't do that (stack unwinds by then).
Your code should look more like:
int handleLuaError(lua_State* L) {
const char * msg = lua_tostring(L, -1);
luaL_traceback(L, L, msg, 2);
lua_remove(L, -2); // Remove error/"msg" from stack.
return 1; // Traceback is returned.
}
void readLua(const char *filename) {
SPDLOG_INFO("readLua {}", filename);
lua_pushcfunction(luaState, handleLuaError);
if (LUA_OK != (luaL_loadfile(luaState, filename) || lua_pcall(luaState, 0, 0, -2))) {
// handleLuaError's index ^^^
handleError("Reading file %s: %s", filename, lua_tostring(luaState, -1));
lua_pop(luaState, 1); // Pop traceback from stack.
}
lua_pop(luaState, 1); // Pop handleLuaError from stack.
}
Now, that's a rather simple implementation. You should consider splitting luaL_loadfile and lua_pcall to react accordingly to errors related directly to loading a file. Again, you can refer to interpreter's source code: dofile and then dochunk.
Additionally, the example above lacks most of important checks, especially test if lua_tostring was successful, unless you are more than 100% sure that the returned error can always be converted easily into a string.
It seems that you have two states coexisting: luaState and sometimes L. I suggest looking into that, it may spare you some problems in future.
One more thing, in addition to luaL_traceback you may also be interested in luaL_where. It's used internally with luaL_error.

MFC ODBC SQLConfigDataSource() Unhandled Exception

I'm trying to update an old c++ MFC program and SQLConfigDataSource is causing an unhandled exception when I try to create a DSN. The error message says:
Unhandled exception at 0x00007FFC97D89129 (KernelBase.dll):
0x0000087A (parameters: 0xFFFFFFFF887A0001, 0x0000000000000053)
The code runs correctly and functions as it should, but I can't seem to get rid of this error.
int mlen;
char* szDesc = new char[256];
sprintf_s(szDesc, 256, "DSN=%s?DBQ=%s?FIL=MicrosoftAccess?",
IV_DATABASE_NAME, // DSN name
sDBPath); // full file name for accdb file
mlen = strlen(szDesc);
for (int i = 0; i < mlen; i++) {
if (szDesc[i] == '?')
szDesc[i] = '\0';
}
SQLConfigDataSource(NULL, ODBC_ADD_DSN,
"Microsoft Access Driver (*.mdb, *.accdb)",
(LPCSTR)szDesc);
delete szDesc;
The arguments for SQLConfigDataSource are ill formed. See:
SQLConfigDataSource Function
And:
ConfigDSN Function
Each pair is terminated with a null byte, and the entire list is
terminated with a null byte. (That is, two null bytes mark the end of
the list.)
I've had this working for over a decade now and call it like:
if( ! bOk )//failed to open the default database for lack of DSN
{
TRACE("Could not find DSN\n");
BOOL ret= SQLConfigDataSource(
NULL,
ODBC_ADD_DSN,
(LPSTR) "Microsoft Access Driver (*.mdb)\0",
(LPSTR) "DSN=MS Access Database\0"
"Description=MS Access Database\0"
);
if( ! ret )
{
AfxMessageBox( _T("The 'Data Source Name' failed to install\nPlease call My Company\n800-555-5555") );
return FALSE;
}
}
Note that the first two extra nulls are redundant, but they do no harm. But the last line follows the two null, end of list, rule.
"Description=MS Access Database\0"
You should be checking the return value of SQLConfigDataSource. And you can call SQLInstallerError as described in Diagnostics. Also, the comments state that the keywords and values should not contain ?.
The error was occurring when Microsoft Access Database Engine 2016 Redistributable was installed. I installed the 2010 Redistributable and it runs perfectly without any issues.

Libzip - Error: Error while opening the archive : no error

I'm trying to find out the solution to solve a problem;
In fact, i'm writing my own tool to make saves using libzip in C++ to compress the files.
Absolutly not finished but i wanted to make some tests, then i do and obtain a "funny" error from the log.
Here's my function:
void save(std::vector<std::string> filepath, std::string savepath){
int err;
savepath += time(NULL);
zip* saveArchive = zip_open(savepath.c_str(), ZIP_CREATE , &err);
if(err != ZIP_ER_OK) throw xif::sys_error("Error while opening the archive", zip_strerror(saveArchive));
for(int i = 0; i < filepath.size(); i++){
if(filepath[i].find("/") == std::string::npos){}
if(filepath[i].find(".cfg") == std::string::npos){
err = (int) zip_file_add(saveArchive, filepath[i].c_str(), NULL, NULL);
if(err == -1) throw xif::sys_error("Error while adding the files", zip_strerror(saveArchive));
}
}
if(zip_close(saveArchive) == -1) throw xif::sys_error("Error while closing the archive", zip_strerror(saveArchive));
}
I get a => Error : Error while opening the archive : No error
And, of course, i didn't have any .zip written.
If you could help me, thanks to you !
The documentation for zip_open says that it only sets *errorp if the open fails. Either test for saveArchive == nullptr or initialize err to
ZIP_ER_OK.
P.S. The search for '/' does nothing. Did you mean to put a continue in that block?
The other problematic line is:
savepath += time(NULL);
If that is the standard time function, that returns a time in seconds since the epoch. That will probably get truncated to a char, and then that char appended to the file name. That will cause strange characters to appear in the filename! I suggest using std::chrono to convert to text.

c++ Unhandled exception - how to debug

I have a problem when running a testcase in debug-mode: I get a pop-up-box with the message "Unhandled exception at 0x7c812fd3 in Test.exe: 0xE0000003: 0xe0000003.". The code breaks in free.c:
void __cdecl _free_base (void * pBlock)
{
int retval = 0;
if (pBlock == NULL)
return;
RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
retval = HeapFree(_crtheap, 0, pBlock);
if (retval == 0)
{
errno = _get_errno_from_oserr(GetLastError());
}
}
at line "retval =..." with _crtheap = 0x00df0000 and pBlock = 0x967c93d3. The call stack breaks at "kernel32.dll!7c812fd3() " and another entry further down in the call stack:
">msvcr100d.dll!_free_base(void * pBlock=0x967c93d3) Line 50 + 0x13 bytes".
I have googled quite a bit and the problem might come from freeing memory severel times.
Despite this vague and messy description can anyone hint how to locate the problem ? and maybe how to fix it ?
What strikes me a bit odd is that I do not experience this when running the test in release-mode...
Kind regards,
Svend
Have you tried to run these testcases under visual studio debugger?
Debugger should catch this exception and you can verify call stack and locate where issue is.

Why does GetLastError() return different codes during debug vs "normal" execution?

try
{
pConnect = sess->GetFtpConnection(ftpArgs.host, ftpArgs.userName, ftpArgs.password, port, FALSE );
}
catch (CInternetException* pEx)
{
loginErrCode = GetLastError();
printf("loginErrCode: %d\n", loginErrCode);
if(loginErrCode == 12013)
{
printf("Incorrect user name!\n");
exit(0);
}
else if(loginErrCode == 12014)
{
printf("Incorrect password!\n");
exit(0);
}
else if(loginErrCode == 12007)
{
printf("Incorrect server name!\n");
exit(0);
}
else //display all other errors
{
TCHAR sz[1024];
pEx->GetErrorMessage(sz, 1024);
printf("ERROR! %s\n, sz);
pEx->Delete();
exit(0);
}
When this code runs from visual studio with an intentional incorrect user name, GetLastError() returns 12014 (expected).
However, when running the same code from the command line (with the same exact incorrect username) GetLastError() returns 2? (the GetErrorMessage() does return incorrect password)
I do not understand what the difference is.
In addition, I ran the program from the command line while attaching the process to it in visual studio, to debug. I received 12014.
Whenever the debugger is involved, I get 12014. When I run the executable "normally" with the same parameters, I get 2.
Are the WinInet error codes not being found when I run the program outside of the debugger? Do I need to compile the program differently?
Any help is appreciated. Thank You.
My memory is a little hazy in this regard, but what happens if you use the m_dwError field of the CInternetException object instead of calling GetLastError()?
My guess is that something is causing the error code to be reset between when the actual error and your call to GetLastError(). I don't know why this happens when running outside the debugger but not inside the debugger. However, MFC caches the error code that caused the exception in the thrown object, so you should be able to use the cached value regardless of what API calls have happened since the exception was thrown.
GetErrorMessage() returns the correct error string because it uses this m_dwError field, rather than calling GetLastError().