I have a method where I create objects on the heap and return a boolean which indicates if it went well or not.
I am not 100% sure about my bool assignments though in (1); is this legal to do?
bool ret = true;
if (ret = !mRenderBackend) // make sure mRenderBackend is NULL
{
if (mEngineSettings.GetRenderBackend() == OPENGL)
ret = mRenderBackend = mMemoryAllocator.AllocateObject<RenderOpenGL>(); // (1). AllocateObject returns either NULL or object address
}
return ret;
Thanks
You don't really need the bool at all, it sort of makes it harder to follow. I would personally do something like,
if (mRenderBackend == NULL) // make sure mRenderBackend is NULL
{
if (mEngineSettings.GetRenderBackend() == OPENGL)
mRenderBackend = mMemoryAllocator.AllocateObject<RenderOpenGL>(); // (1). AllocateObject returns either NULL or object address
}
return (mRenderBackend != NULL);
Yes, legal.
if (ret = !mRenderBackend)
is equivalent to
ret = !mRenderBackend;
if(ret)
is equivalent to
ret = (mRenderBackend == 0);
if(ret)
Just note that ret will only be defined up to zero/nonzeroness which looks safe in your code.
Related
In the function below I am facing a Dereference error before null check. In the line
SEC_KM_KEKColumn_t *pAdmin1KEKs = pTCGKS->keySet[SEC_KM_Admin1].kc;
There is an error which states directly dereferencing pointer pTCGKS. And also in the line
SEC_ASSERT_MODEL(pDefaultKS != NULL && pTCGKS != NULL);
there is an error which states Dereference before null check (REVERSE_INULL)
check_after_deref: Null-checking pTCGKS suggests that it may be null, but it has already been dereferenced on all paths leading to the check.
Stat_t SEC_COD_SLOW SEC_KM_TCG_Activ(SEC_KM_TCGKeySet_t *pTCGKS, uint32_t rangesSUM, SEC_KM_DefaultKeySet_t *pDefaultKS)
{
Status_t status = STATUS_OK;
uint32_t rangeIndex = 0;
const SEC_KM_KDF_t *pDigestNID = SEC_KM_GetAnybodyDigest();
SEC_KM_KEKColumn_t *pAdmin1KEKs = pTCGKS->keySet[SEC_KM_Admin1].kc;
const SEC_KM_KDF_t *pDigestAID = SEC_KM_TCG_GetSessionCredentials();
SEC_ASSERT_DEBUG(SEC_KM_TCG_GetSessionUserID() == SEC_KM_Admin1);
SEC_ASSERT_MODEL(pDefaultKS != NULL && pTCGKS != NULL);
// Generate Key Chains for all TCG authorities for Original Opal scheme
status = SEC_KM_TCG_Generate(pTCGKS, pDigestNID, pDigestAID);
if (status != STATUS_OK)
{
return status;
}
// Rewrap SDEK from default key storage into Global Range of TCG
status = SEC_KM_RewrapSDEK(&pDefaultKS->SDEKw, &pDefaultKS->keySet.RKEKw, &pDefaultKS->keySet.PKEKw, pDigestNID,
&pTCGKS->DEK[GDEK].SDEK.w, &pAdmin1KEKs[RKEKG].w, &pAdmin1KEKs[PKEK].w, pDigestAID);
if (status != STATUS_OK)
{
return status;
}
status = SEC_KM_TCG_ConvertToSUM(pTCGKS, pDigestNID, rangesSUM);
if (status != STATUS_OK)
{
return status;
}
// After Activation all ranges are unlocked. So unwrap all SDEKs.
for (rangeIndex = 0; rangeIndex < TCG_MAX_RANGE_KEYS; rangeIndex++)
{
status = SEC_KM_TCG_UnwrapUnlockedSDEK(pTCGKS, rangeIndex);
if (status != STATUS_OK)
{
return status;
}
}
return status;
}
It's exactly what it says.
First you dereference pTCGKS, then you check that it isn't null.
Compilers can (and will) optimise out a "late" null check as being effectively redundant for any well-defined program, making your assertion potentially useless.
Move it to before your dereference.
The SEC_ASSERT_MODEL checks for NULL after the line that references it. If pTCGKS is null a runtime error will occur before that check, so it serves no useful purpose.
I assume SEC_ASSERT_MODEL is a precondition check macro - if that is the case you need to perform those checks before using the checked parameters:
SEC_ASSERT_DEBUG(SEC_KM_TCG_GetSessionUserID() == SEC_KM_Admin1);
SEC_ASSERT_MODEL(pDefaultKS != NULL && pTCGKS != NULL);
Status_t status = STATUS_OK;
uint32_t rangeIndex = 0;
const SEC_KM_KDF_t *pDigestNID = SEC_KM_GetAnybodyDigest();
SEC_KM_KEKColumn_t *pAdmin1KEKs = pTCGKS->keySet[SEC_KM_Admin1].kc;
const SEC_KM_KDF_t *pDigestAID = SEC_KM_TCG_GetSessionCredentials();
When I use the following function as isRunning("example.exe"); it always returns 0 no matter if the process is running or not.
I tried making it std::cout << pe.szExeFile; in the do-while loop and it outputs all the processes in the same format as I am trying to pass the function.
The project is multi-byte character set, in case that makes a difference.
bool isRunning(CHAR process_[])
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (pe.szExeFile == process_) // if(!strcmp(pe.szExeFile, process_)) is the correct line here
return true; // If you use this remember to close the handle here too with CloseHandle(pss);
} while (Process32Next(pss, &pe));
}
CloseHandle(pss);
return false;
}
Can't seem to find my mistake.
Thanks for your time.
You are using if (pe.szExeFile == process_) which compares the pointer values. You should be using something like strcmp or _stricmp to compare the actual string values instead.
e.g.
if(strcmp (pe.szExeFile, process_) == 0)
return true;
I need the following for the exception handler in C++ code. Say, I have the following code block:
void myFunction(LPCTSTR pStr, int ncbNumCharsInStr)
{
__try
{
//Do work with 'pStr'
}
__except(1)
{
//Catch all
//But here I need to log `pStr` into event log
//For that I don't want to raise another exception
//if memory block of size `ncbNumCharsInStr` * sizeof(TCHAR)
//pointed by 'pStr' is unreadable.
if(memory_readable(pStr, ncbNumCharsInStr * sizeof(TCHAR)))
{
Log(L"Failed processing: %s", pStr);
}
else
{
Log(L"String at 0x%X, %d chars long is unreadable!", pStr, ncbNumCharsInStr);
}
}
}
Is there any way to implement memory_readable?
The VirtualQuery function might be able to help. The following is a quick stab at how you could implement memory_readable using it.
bool memory_readable(void *ptr, size_t byteCount)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(ptr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
return false;
if (mbi.State != MEM_COMMIT)
return false;
if (mbi.Protect == PAGE_NOACCESS || mbi.Protect == PAGE_EXECUTE)
return false;
// This checks that the start of memory block is in the same "region" as the
// end. If it isn't you "simplify" the problem into checking that the rest of
// the memory is readable.
size_t blockOffset = (size_t)((char *)ptr - (char *)mbi.AllocationBase);
size_t blockBytesPostPtr = mbi.RegionSize - blockOffset;
if (blockBytesPostPtr < byteCount)
return memory_readable((char *)ptr + blockBytesPostPtr,
byteCount - blockBytesPostPtr);
return true;
}
NOTE: My background is C, so while I suspect that there are better options than casting to a char * in C++ I'm not sure what they are.
You can use the ReadProcessMemory function. If the function returns 0, the address is not readable otherwise it is readable.
Return Value
If the function fails, the return value is 0 (zero). To get extended
error information, call GetLastError.
The function fails if the requested read operation crosses into an
area of the process that is inaccessible.
If the function succeeds, the return value is nonzero.
Very new to C++ and having problems returning a vector. I put a breakpoint and the array is correct (populated with all the objects I would expect from the query). But when it returns I get an error:
EXC_BAD_ACCESS
on line m_pComponentContainer->removeAll();
from CCNode.cpp
Which is strange since this is a base class (does NOT inherit from any kind of CC object) although I am extensively using the Cocos2dx framework, its not included in this class.
Im fairly sure this is because something is being deallocated. However like I said Im very new to C++ and not really sure where the problem is. I was hoping to get a little further in development before I had to start worrying about memory management.
int numberOfCards = DatabaseHelper::getNumberOfCards();
//cant be zero
assert(numberOfCards);
std::vector<CardSlot> returnArray(numberOfCards);
sqlite3_stmt * statement;
if (sqlite3_open(this->dbpath.c_str(),&this->cardWarsDB) == SQLITE_OK)
{
const char* query_stmt = "select ID, HP, MP, AbilityText from Cards WHERE ID IN (SELECT DISTINCT cardsID FROM Deck WHERE name = 'All')";
if (sqlite3_prepare_v2(this->cardWarsDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
CardSlot *aCard;
const char* cardID = (const char*)sqlite3_column_text(statement, 0);
const char* cardHP = (const char*)sqlite3_column_text(statement, 1);
const char* cardMP = (const char*)sqlite3_column_text(statement, 2);
const char* cardAbility = (const char*)sqlite3_column_text(statement, 3);
if (cardID != NULL) {
std::string imageName = ".png";
imageName = cardID + imageName;
aCard = (CardSlot *)CardSlot::spriteWithFile(imageName.c_str());
}
if (cardID != NULL) {
aCard->cardID = std::string(cardID);
cocos2d::CCLog("DB returned results, cardID: %s",aCard->cardID.c_str());
}
if (cardHP != NULL) {
aCard->cardHP = std::string(cardHP);
cocos2d::CCLog("DB returned results, cardHP: %s",aCard->cardHP.c_str());
}
if (cardMP != NULL) {
aCard->cardMP = std::string(cardMP);
cocos2d::CCLog("DB returned results, cardMP: %s",aCard->cardMP.c_str());
}
if (cardAbility != NULL) {
aCard->cardAbility = std::string(cardAbility);
cocos2d::CCLog("DB returned results, cardAbility: %s",aCard->cardAbility.c_str());
}
numberOfCards--;
returnArray[numberOfCards] = *aCard;
}
sqlite3_finalize(statement);
}
sqlite3_close(this->cardWarsDB);
return returnArray;
}
Here is a screenshot of the stack trace. I was just looking at it, and it seems that it is the CardSlot objects are the culprits.
But still dont know how to "retain" them, but Ill look at some Cocos documentation.
NOTE1
It looks like your CardSlot is not safe to copy. You copy CardSlots in at least two places:
aCard = * CardSlot::spriteWithFile(imageName.c_str()); (also a memory leak assuming spriteWithFile returns CardSlot *; the "temporary" is not destructed)
returnArray[numberOfCards] = aCard;
From what I can tell, you are probably keeping a CCSprite pointer in CardSlot and destroying it (with delete) in your CardSlot destructor. However, this pointer gets destroyed multiple times because of the copies, which causes your crash.
You need to redesign your class so it can either be safely copied, or refactor your code so that you make no copies (e.g. by using a vector<shared_ptr<CardSlot> > to hold pointers to the instances).
I have edited the code to use more pointers rather then passing around and filling my array with objects. However I think a big thing that helped fix it was using cocos2d::CCArray instead of a std::vector. Most of my classes are children of Cocos2d classes (CCSprites, and CCLayers) and so using its own array data type makes sense.
cocos2d::CCArray DatabaseHelper::getAllCards()
{
int numberOfCards = DatabaseHelper::getNumberOfCards();
//cant be zero
assert(numberOfCards);
cocos2d::CCArray returnArray(numberOfCards);
sqlite3_stmt * statement;
if (sqlite3_open(this->dbpath.c_str(),&this->cardWarsDB) == SQLITE_OK)
{
const char* query_stmt = "select ID, HP, MP, AbilityText from Cards WHERE ID IN (SELECT DISTINCT cardsID FROM Deck WHERE name = 'All')";
if (sqlite3_prepare_v2(this->cardWarsDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
CardSlot* aCard;
const char* cardID = (const char*)sqlite3_column_text(statement, 0);
const char* cardHP = (const char*)sqlite3_column_text(statement, 1);
const char* cardMP = (const char*)sqlite3_column_text(statement, 2);
const char* cardAbility = (const char*)sqlite3_column_text(statement, 3);
if (cardID != NULL) {
std::string imageName = ".png";
imageName = cardID + imageName;
aCard = CardSlot::spriteWithFile(imageName.c_str());
}
if (cardID != NULL) {
aCard->cardID = std::string(cardID);
cocos2d::CCLog("DB returned results, cardID: %s",aCard->cardID.c_str());
}
if (cardHP != NULL) {
aCard->cardHP = std::string(cardHP);
cocos2d::CCLog("DB returned results, cardHP: %s",aCard->cardHP.c_str());
}
if (cardMP != NULL) {
aCard->cardMP = std::string(cardMP);
cocos2d::CCLog("DB returned results, cardMP: %s",aCard->cardMP.c_str());
}
if (cardAbility != NULL) {
aCard->cardAbility = std::string(cardAbility);
cocos2d::CCLog("DB returned results, cardAbility: %s",aCard->cardAbility.c_str());
}
numberOfCards--;
returnArray.addObject(aCard);
}
sqlite3_finalize(statement);
}
sqlite3_close(this->cardWarsDB);
return returnArray;
}
//incase sql fails, close db and created a "FAILED" card
sqlite3_close(this->cardWarsDB);
cocos2d::CCLog("DB returned error: cant open char catagories file");
cocos2d::CCArray failedReturnArray(1);
CardSlot * aCard;
aCard->cardID = std::string("FAILED");
aCard->cardHP = std::string("FAILED");
aCard->cardMP = std::string("FAILED");
aCard->cardAbility = std::string("FAILED");
failedReturnArray.addObject(aCard);
return failedReturnArray;
}
Also in case anyone cares here is CardSlot (not much to it, only built the constructor at this time):
CardSlot * CardSlot::spriteWithFile(const char *pszFileName)
{
CCLOG("CardSlot::spriteWithFile");
CardSlot * aCard = new CardSlot();
if (aCard && aCard->initWithFile(pszFileName))
{
aCard->cardID = pszFileName;
aCard->scheduleUpdate();
aCard->autorelease();
return aCard;
}
CC_SAFE_DELETE(aCard);
return NULL;
}
The only thing Im concerned about is that I think my CCArray should be a pointer. But its working now and learning all the memory management "tricks of the trade" will come in time, the more I work with C++
Thanks #nneonneo for all the help Im sure your fix would have worked and I tried but no matter what I did couldnt get the vector to work. I 1up'd you as much as I could but really this is the "Answer" I implemented.
The returnArray is declared local to the function, it will be deallocated when the function returns. You would need to either declare it as static or move the declaration to outside the function.
I am reading the source code of CString in MFC. I am very curious about the implementation way of constructor CString::CString(LPCTSTR lpsz).
In my understanding, before copying the string indicated by lpsz, it only needs check whether lpsz is NULL but no need to combine with checking if HIWORD(lpsz) is NULL.
Is any MFC guy passing here and willing to give some explanations?
CString::CString(LPCTSTR lpsz)
{
Init();
if (lpsz != NULL && HIWORD(lpsz) == NULL)
{
UINT nID = LOWORD((DWORD)lpsz);
if (!LoadString(nID))
TRACE1("Warning: implicit LoadString(%u) failed\n", nID);
}
else
{
int nLen = SafeStrlen(lpsz);
if (nLen != 0)
{
AllocBuffer(nLen);
memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR));
}
}
}
It checks whether it is passed an actual pointer or an integer resource identifier from MAKEINTRESOURCE. In the latter case it loads the string from the resources.
That is for loading a string resource. See the LoadString() call.