Initialize pid_t variable - c++

I have an error reported by Valgrind:
==5644== Conditional jump or move depends on uninitialised value(s)
This is happening for a variable of type pid_t.
My code is the following:
GmpPipePlayer::GmpPipePlayer( IOBase *pIO, Referee *pBack, PieceColor pc, int size, const DataBoard *pBd, int handicap, const char *cmd_line, int bDebug )
: GmpPlayer(pIO, pBack, pc, size, pBd, handicap, bDebug)
{
int down[2], up[2];
pid_t _pid; //here the var is declared
pipe(down);
pipe(up);
_pid = fork();
if (_pid < 0)
exit(1);
if (_pid == 0)
{
close(down[1]);
close(up[0]);
dup2(down[0], 0);
dup2(up[1], 1);
execl("/bin/sh", "sh", "-c", cmd_line, NULL);
_exit(1);
}
close(down[0]);
close(up[1]);
_down = down[1];
_up = up[0];
_reader_thd = new Thread(reader_wrapper, this);
}
GmpPipePlayer::~GmpPipePlayer()
{
if (_pid > 0) //valgrind is reporting that the error is here!!
{
kill(_pid, SIGTERM);
_pid = 0;
}
if (_up)
{
close(_up);
_up = 0;
}
if (_down)
{
close(_down);
_down = 0;
}
delete _reader_thd
}
So, I think the problem is the _pid is not initialized, how should initialize this variable? I tried in this way:
pid_t _pid=0;
but this is still causing the same error. That piece of code is called many times during the process.

It appears that you have two variables called _pid - the local that you declared in the constructor:
pid_t _pid; //here the var is declared
and the one that you access in the destructor:
if (_pid > 0) //valgrind is reporting that the error is here!!
These variables are not the same: the one that you access in the destructor must be a global or an instance variable (more likely).
Since you rely on _pid to pass the state from the constructor to the destructor, you need to remove the local declaration from the constructor, and initialize the other _pid as appropriate. If it is an instance variable, add its initialization to the initializer list, like this:
GmpPipePlayer::GmpPipePlayer( IOBase *pIO, Referee *pBack, PieceColor pc, int size, const DataBoard *pBd, int handicap, const char *cmd_line, int bDebug )
: GmpPlayer(pIO, pBack, pc, size, pBd, handicap, bDebug), _pid(0) {
... // HERE ------------------^
}

Related

Calling an external function with GetProcAddress crashes the app

I've been trying to call an external function with the GetProcAddress function but everytime i call the function it crashes the console, ive been looking but in every post i get the same final solution but when i try it in my DLL it crashes the app.
Here's the code:
#include <Windows.h>
#include <vector>
#include "SDK\plugin.h"
typedef void (*logprintf_t)(char* format, ...);
logprintf_t logprintf;
// static void* m_AMXExports[44];
typedef bool (PLUGIN_CALL *ServerPluginLoad_t)(void **data);
typedef void (PLUGIN_CALL *ServerPluginUnload_t)();
typedef unsigned int (PLUGIN_CALL *ServerPluginSupports_t)();
typedef void (PLUGIN_CALL *ServerPluginProcessTick_t)();
typedef int (PLUGIN_CALL *ServerPluginAmxLoad_t)(AMX *amx);
typedef int (PLUGIN_CALL *ServerPluginAmxUnload_t)(AMX *amx);
struct Plugins
{
void* AppData[256];
SUPPORTS_FLAGS FlagSupport;
HMODULE Module;
ServerPluginLoad_t LOAD;
ServerPluginUnload_t UNLOAD;
ServerPluginSupports_t SUPPORTS;
ServerPluginProcessTick_t PROCESSTICK;
// AMX Plugin Interface
ServerPluginAmxLoad_t AMXLOAD;
ServerPluginAmxUnload_t AMXUNLOAD;
};
Plugins* ServerPlugins;
void **ppPluginData ;
extern void *pAMXFunctions;
//native LoadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
bool validfunc = false;
char *path;
amx_StrParam(amx, params[1], path);
logprintf("Loading plugin %s", path);
ServerPlugins = new Plugins();
ServerPlugins->Module = LoadLibraryA(path);
if (ServerPlugins->Module == NULL)
{
delete ServerPlugins;
logprintf("Failed loading plugin %s (Error: %d)", path, GetLastError());
return 0;
}
logprintf("NULL");
ServerPlugins->LOAD = (ServerPluginLoad_t)GetProcAddress(ServerPlugins->Module, "Load");
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
ServerPlugins->SUPPORTS = (ServerPluginSupports_t)GetProcAddress(ServerPlugins->Module, "Supports");
if (ServerPlugins->LOAD == NULL || ServerPlugins->SUPPORTS == NULL || ServerPlugins->UNLOAD == NULL)
{
logprintf(" Plugin doesnt conform to architecture");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 1");
ServerPlugins->FlagSupport = (SUPPORTS_FLAGS)ServerPlugins->SUPPORTS();
if ((ServerPlugins->FlagSupport & SUPPORTS_VERSION_MASK) > SUPPORTS_VERSION)
{
logprintf("Unsupported Version; unloading.");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 2");
if ((ServerPlugins->FlagSupport & SUPPORTS_AMX_NATIVES) > SUPPORTS_VERSION)
{
ServerPlugins->AMXLOAD = (ServerPluginAmxLoad_t)GetProcAddress(ServerPlugins->Module, "AmxLoad");
ServerPlugins->AMXUNLOAD = (ServerPluginAmxUnload_t)GetProcAddress(ServerPlugins->Module, "AmxUnload");
}
else
{
ServerPlugins->AMXLOAD = NULL;
ServerPlugins->AMXUNLOAD = NULL;
logprintf("Any Abstract Machine has been loaded");
}
logprintf("NULL 3");
if ((ServerPlugins->FlagSupport & SUPPORTS_PROCESS_TICK) != 0)
{
ServerPlugins->PROCESSTICK = (ServerPluginProcessTick_t)GetProcAddress(ServerPlugins->Module, "ProcessTick");
}
else
{
ServerPlugins->PROCESSTICK = NULL;
}
logprintf("NULL 4"); //debugging
ServerPlugins->AppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ServerPlugins->AppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ServerPlugins->AppData)) //i didnt put it as &ServerPlugins->AppData because it causes an error
{
logprintf("Initialized failed loading plugin %s", path);
FreeLibrary(ServerPlugins->Module);
logprintf("NULL 5");
delete ServerPlugins;
return false;
}
logprintf("Plugin %s loaded", path);
return true;
}
//native UnloadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
char *path;
amx_StrParam(amx, params[1], path);
ServerPlugins->Module = GetModuleHandle((LPCTSTR)path);
if (ServerPlugins->Module != NULL)
{
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
if (ServerPlugins->UNLOAD != NULL)
{
ServerPlugins->UNLOAD();
FreeLibrary(GetModuleHandleA(path));
logprintf("Library %s has been unloaded correctly", path);
return 1;
}
else
{
logprintf("Unloading library %s failed (Error: %d)", GetLastError());
return 0;
}
}
return 1;
}
PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData)
{
pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
return 1;
}
PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
}
PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports()
{
return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}
AMX_NATIVE_INFO projectNatives[] =
{
{ "LoadLibrary", my_LoadLibrary },
{ "UnloadLibrary", my_UnloadLibrary }
};
PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx)
{
return amx_Register(amx, projectNatives, -1);
}
PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx)
{
return AMX_ERR_NONE;
}
You have a memory leak in convertCharArrayToLPCWSTR(). You are never freeing the wchar_t* that you allocate. The convertCharArrayToLPCWSTR() function itself is not needed, you can simply pass the char* path as-is to LoadLibraryA() instead:
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Module = LoadLibraryA(path);
You are not checking if ServerPlugins->UNLOAD is successfully loaded by GetProcAddress("Unload") or not.
You are using GetProcAddress("Load") for both ServerPlugins->LOAD and ServerPlugins->AMXLOAD, and GetProcAddress("Unload") for both ServerPlugins->UNLOAD and ServerPlugins->AMXUNLOAD. That is very fishy to me. Does the DLL really use the same exports for AMX and non-AMX entry points? If so, that is very bad design, considering that ServerPluginLoad_t has a very different signature than ServerPluginAmxLoad_t, and the same for ServerPlugin(Amx)Unload_t. That is a corrupted call stack waiting to happen. It would be much safer to have the DLL export separate AmxLoad() and AmxUnload() functions instead.
For that matter, the SUPPORTS_AMX_NATIVES and SUPPORTS_PROCESS_TICK flags are redundant, since GetProcAddress() would tell you if those exports are available or not.
As for the crash when calling ServerPlugins->LOAD, I do not see you initializing ppData with any data before passing it to Load(). Certainly not the PLUGIN_DATA_AMX_EXPORTS and PLUGIN_DATA_LOGPRINTF slots, at least:
ppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ppData))
So even if the call to Load() itself did not crash, the DLL would still likely crash at a later time when it tries to use its local pAMXFunctions and logprintf pointers that were assigned in Load().
For that matter, why are you passing things like that as a void* array instead of a struct? That would have been much safer, eg:
struct PluginInitData
{
void* pAMXFunctions;
logprintf_t logprintf;
...
};
typedef bool (__stdcall *ServerPluginLoad_t)(PluginInitData* data);
PluginInitData pInitData;
pInitData.pAMXFunctions = pAMXFunctions;
pInitData.logprintf = &logprintf;
...
if (!(ServerPlugins->LOAD)(&pInitData))
extern "C" bool __stdcall Load(PluginInitData* data)
{
pAMXFunctions = data->pAMXFunctions;
logprintf = data->logprintf;
...
return true;
}
Update: you have fixed most of the issues I mentioned, but now I see that your my_UnloadLibrary() function is implemented wrong. DO NOT call GetModuleHandle() or GetProcAddress() at all, use the existing Module and UNLOAD pointers that were initialized earlier in my_LoadLibrary().
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Path = path;
...
}
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
if (ServerPlugins)
{
if (ServerPlugins->UNLOAD != NULL)
ServerPlugins->UNLOAD();
if (ServerPlugins->Module != NULL)
{
FreeLibrary(ServerPlugins->Module);
ServerPlugins->Module = NULL;
}
logprintf("Library %s has been unloaded", ServerPlugins->Path);
delete ServerPlugins;
ServerPlugins = NULL;
}
return 1;
}
If you are still having problems with Load() crashing, then you are just going to have to use your compiler's debugger to find out what is actually happening at run-time. The code shown so far should not be crashing, so either you have a calling convention mismatch, or a data alignment mismatch, or corrupted memory, or something like that. We can't run you debugger for you.

Segmentation fault in constructor in c++

So I have the cl_Page class:
class cl_Page{
public:
cl_Page(cl_LessonMoment *parent_param);
cl_Page(cl_SoftRoot *parent_param);
int parent_type;
cl_LessonMoment *parent_lmoment;
cl_SoftRoot *parent_softroot;
char id[256];
//<content>
//Backgrounds.
str_Color bgcolor;
cl_Image bgimage;
//Actual content
vector<cl_Textbox> textboxes;
vector<cl_Button> buttons;
vector<cl_Image> images;
//</content>
cl_Textbox* AddTextbox();
cl_Button* AddButton();
cl_Image* AddImage(char *filename = nullptr);
};
and the cl_Page constructors:
cl_Page::cl_Page(cl_LessonMoment *parent_param) : bgimage(nullptr){ //here is the segfault
parent_lmoment = parent_param;
parent_type = 1;
id[0] = '\0';
SetColor(bgcolor, 0xffffffff);
}
cl_Page::cl_Page(cl_SoftRoot *parent_param): bgimage(nullptr){ // or here if i call this constructor
/*parent_softroot = parent_param;
parent_type = 2;
id[0] = '\0';
SetColor(bgcolor, 0xffffffff);*/
}
What happens is that, no matter how I call the constructors, or no matter which one I call (the second is all commented out; so basically empty), global, local or dynamically, in a function or as a member object, I get a segmentation fault which appears to be right on the cl_Page::cl_Page(cl_LessonMoment *parent_param) : bgimage(nullptr){ line. The call stack looks like this:
#0 77C460CB strcat() (C:\WINDOWS\system32\msvcrt.dll:??)
#1 0022F168 ?? () (??:??)
#2 00401905 cl_Page::cl_Page(this=0x22fbe8, parent_param=0x0) (F:\Scoala\C++\EduSoftViewer_Parser\sources\classes\soft_tree\page.cpp:10)
#3 00402B8A main() (F:\Scoala\C++\EduSoftViewer_Parser\sources\main.cpp:11)
On some builds before I am writing this, (with exactly the same issue) the #1 position on the call stack, where now is ?? () (??:??) was ntdll!RtlDosApplyFileIsolationRedirection_Ustr() (C:\WINDOWS\system32\ntdll.dll:??).
So my question is: Does anybody know what is causing this? I really need to get this working.
If anything is unclear, just ask and I'll provide additional information.
EDIT: To clarify: I'm under Windows XP SP2 and running Code::Blocks with gcc.
EDIT 2: The cl_Image constructor:
cl_Image::cl_Image(char *filename_param){
if (filename == nullptr){
filename[0] = '\0';
}
else{
strcpy(filename, filename_param);
}
SetPosition(position, 0, 0);
id[0] = '\0';
visible = 1;
z_index = 0;
}
This class doesn't contain any object members, with the exception of a POD struct, position
EDIT 3: The cl_Image class:
class cl_Image{
public:
cl_Image(char* filename_param = nullptr);
str_Position position;
char filename[256];
char id[256];
bool visible;
int z_index;
};
str_Position is just a struct of 2 ints.
Pretty sure this is your problem:
cl_Image::cl_Image(char *filename_param){
if (filename == nullptr){ // <<==== filename??? try using the param.
filename[0] = '\0';
}
Try this:
cl_Image::cl_Image(char *filename_param){
if (filename_param == nullptr){
filename[0] = '\0';
}
I'll guess that bgimage can't be initialized with nullptr.

passing structure object as parameter to a thread

This code runs successfully and MQStruct constructor initialized the values as well, I can see in ExecuteThread function but in TestFunction, I get the garbage values for MQStruct.
I am passing address of struct "&MQStructObj" to _beginthreadex for parameters and This is the problem I guess
struct MQStruct {
MQStruct()
{
pointer=NULL;
serviceName=NULL;
durability=0;
msgType=0;
msgHeader=0;
msgId=NULL;
payload=NULL;
payloadSize=0;
ttl=0;
priority=0;
}
void* pointer;
wchar_t *serviceName;
int durability;
int msgType;
int msgHeader;
wchar_t *msgId;
wchar_t *payload;
int payloadSize;
int ttl;
int priority;
};
int ExecuteThread() {
HANDLE heartBeatThread;
unsigned int hbThreadID;
int result = 0;
MQStruct MQStructObj;
MQStructObj.pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, &MQStructObj, 0/*CREATE_SUSPENDED*/, &hbThreadID);
if ( heartBeatThread == 0 )
{
result = -1;
LogEvent(DEBUG_LOG,0, "Fail to create thread");
}
CloseHandle(heartBeatThread);
return result;
}
You guessed correctly.
You're passing the address of a local variable to your thread-proc-startup, then leaving scope (and destroying the object in the process). References to this object in your thread proc are there-after undefined behavior.
Dynamically allocate one with new and let the thread proc delete it.
MQStructObj is declared on the stack so will go out of scope and potentially be overwritten as soon as ExecuteThread completes.
If you want to use a stack object here, you'll need to add some synchronisation to allow your new thread to copy from MQStructObj before ExecuteThread returns.
Alternatively, normally preferably, you could allocate MQStructObj dynamically and leave the new thread to clean it up at its leisure
MQStruct* MQStructObj = new MQStruct();
MQStructObj->pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, MQStructObj, 0, &hbThreadID);
if ( heartBeatThread == 0 ) { // error
delete MQStructObj;
result = -1;
}
// ownership of MQStructObj transferred to new thread

constructor not getting called?

Ive been staring at my code and I can't figure out why on earth my constructor is not gettign called.
It's just ignoring my constructor completely (i've check with stepping with debugger).
Here's my testapp:
using namespace MyEngine;
int _tmain(int argc, _TCHAR* argv[])
{
TestManager* testMgr = new TestManager();
testMgr->RunAllTests();
delete testMgr;
getchar();
return 0;
}
TestManager.h:
namespace MyEngine
{
class TestManager
{
public:
TestManager();
TestManager(uint64_t RepeatTimes);
~TestManager();
bool RunAllTests();
bool RunMemoryTests();
private:
Engine* mEngine;
ILogManager* mLogger;
MemoryTestManager* mMemTestMgr;
uint64_t mRepeatTimes;
};
}
and TestManager.cpp
namespace MyEngine
{
TestManager::TestManager()
{
TestManager(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
TestManager::~TestManager()
{
}
/* Runs all testing modules */
bool TestManager::RunAllTests()
{
bool res = true;
/* Init Engine */
if(mEngine->Init(0,0,0))
{
res = true;
res && mEngine->GetRenderManager()->Init();
res && mLogger->Init(true,true);
res && mEngine->GetMemoryManager()->Init(false);
}
else
return false;
/* Start Engine */
mEngine->Start();
/* Get logger */
mLogger = mEngine->GetLogger();
/* Run Memory Tests */
res &= RunMemoryTests();
if (res)
mLogger->LogInfo("TEST: TESTING SUCCESSFULL");
else
mLogger->LogError("TEST: TESTING FAILED");
return res;
}
/* Runs all memory tests */
bool TestManager::RunMemoryTests()
{
bool res = true;
res &= mMemTestMgr->AllocateTest();
res &= mMemTestMgr->ReferenceTest();
if (res)
mLogger->LogInfo("TEST: RunMemoryTests SUCCESSFULL");
else
mLogger->LogError("TEST: RunMemoryTests FAILED");
return res;
}
}
You cant call another constructor from the same class. I'd refactor the init code into a separate method and call it from both constructors:
namespace MyEngine
{
TestManager::TestManager()
{
Init(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
Init(RepeatTimes);
}
void TestManager::Init(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
}
When you call TestManager(1); inside your TestManager::TestManager() constructor, you're creating another instance of TestManager, using the constructor TestManager::TestManager(uint64_t).
You can't do this on C++, you have to create either a init method, were you set the instance variables to whatever you want, or use optional parameters:
TestManager(uint64_t RepeatTimes = 0);
Then, if you create an instance of TestManager without arguments, you will be calling the TestManager::TestManager(uint64_t)constructor with 0 as the uint64_t argument.
you can't call a default constructor from a overloaded constructor. Why don't you simply create you object like this:
TestManager* testMgr = new TestManager(1);
Using a default argument (as per fontanini's answer) will do what you want in this case.
But if this is a simplified example and you really do want to delegate to another constructor, then that's not possible in C++03 - the line TestManager(1) just constructs a temporary object which goes unused (and the line will probably be optimized out unless the TestManager(uint64_t) constructor has side effects).
However, you can do what you're aiming for here with a C++11 compiler and the following syntax:
TestManager::TestManager() :
TestManager(1)
{
}

How to make upnp action?

I want to implement port-forwarding using intel-upnp.
I got XML data like:
Device found at location: http://192.168.10.1:49152/gatedesc.xml
service urn:schemas-upnp-org:service:WANIPConnection:1
controlurl /upnp/control/WANIPConn1
eventsuburl : /upnp/control/WANIPConn1
scpdurl : /gateconnSCPD.xml
And now, I want to make upnp-action. But, I don't know how to make it.
If you know some code snippet or helpful URL in C, please tell me.
char actionxml[250];
IXML_Document *action = NULL;
strcpy(actionxml, "<u:GetConnectionTypeInfo xmlns:u=\"urn:schemas-upnp- org:service:WANCommonInterfaceConfig:1\">");
action = ixmlParseBuffer(actionxml);
int ret = UpnpSendActionAsync( g_handle,
"http:192.168.10.1:49152/upnp/control/WANCommonIFC1",
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",
NULL,
action,
upnp_callback,
NULL);
I know this is an old question, but it can be kept for reference. You can take a look at the sample code in the libupnp library here: https://github.com/mrjimenez/pupnp/blob/master/upnp/sample/common/tv_ctrlpt.c
The relevant code is in the function TvCtrlPointSendAction():
int TvCtrlPointSendAction(
int service,
int devnum,
const char *actionname,
const char **param_name,
char **param_val,
int param_count)
{
struct TvDeviceNode *devnode;
IXML_Document *actionNode = NULL;
int rc = TV_SUCCESS;
int param;
ithread_mutex_lock(&DeviceListMutex);
rc = TvCtrlPointGetDevice(devnum, &devnode);
if (TV_SUCCESS == rc) {
if (0 == param_count) {
actionNode =
UpnpMakeAction(actionname, TvServiceType[service],
0, NULL);
} else {
for (param = 0; param < param_count; param++) {
if (UpnpAddToAction
(&actionNode, actionname,
TvServiceType[service], param_name[param],
param_val[param]) != UPNP_E_SUCCESS) {
SampleUtil_Print
("ERROR: TvCtrlPointSendAction: Trying to add action param\n");
/*return -1; // TBD - BAD! leaves mutex locked */
}
}
}
rc = UpnpSendActionAsync(ctrlpt_handle,
devnode->device.
TvService[service].ControlURL,
TvServiceType[service], NULL,
actionNode,
TvCtrlPointCallbackEventHandler, NULL);
if (rc != UPNP_E_SUCCESS) {
SampleUtil_Print("Error in UpnpSendActionAsync -- %d\n",
rc);
rc = TV_ERROR;
}
}
ithread_mutex_unlock(&DeviceListMutex);
if (actionNode)
ixmlDocument_free(actionNode);
return rc;
}
The explanation is that you should create the action with UpnpMakeAction() if you have no parameters or UpnpAddToAction() if you have parameters to create your action, and then send it either synchronously or asynchronously.