mfc sdi application cdocument dosave error 0xFEEEFEEE - c++

in my MFC SDI application, i'm trying to override CDocument::DoSave to save my document. I'm using a third part component (TxTextControl) to build a text control. When i save the document, the file is created, but after about one minute my app crashes rising read access error 0xFEEEFEEE, in ole32.dll.
This is my code, txtCtrl is my component:
BOOL CEditorTxDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
{
CString path, nome;
VARIANT vt1, vt2, vt3;
POSITION pos = GetFirstViewPosition();
CEditorTxView *pView = (CEditorTxView*)this->GetNextView(pos);
VariantInit(&vt1);
vt1.vt = VT_INT;
vt1.intVal = -1;
VariantInit(&vt2);
vt2.vt = VT_INT;
vt2.intVal = 3;
VariantInit(&vt3);
vt3.vt = VT_BOOL;
vt3.boolVal = FALSE;
if (lpszPathName == NULL) {
CFileDialog fSaveDlg(FALSE);
fSaveDlg.m_pOFN->lpstrFilter = _T("File Tx (*.tx)");
fSaveDlg.m_pOFN->lpstrDefExt = _T("tx");
fSaveDlg.m_pOFN->lpstrTitle = _T("Salva documento");
fSaveDlg.m_pOFN->lpstrInitialDir = _T("c:");
if(fSaveDlg.DoModal()==IDOK)
{
path = fSaveDlg.GetPathName();
nome = fSaveDlg.GetFileName();
pView->txtCtrl.Save(path, vt1, vt2, vt3);
SetTitle(nome);
SetModifiedFlag(FALSE);
SetPathName(path);
}
} else {
pView->txtCtrl.Save(GetPathName(), vt1, vt2, vt3);
SetModifiedFlag(FALSE);
}
return TRUE;
}

Magic debug values:
FEEEFEEE Used by Microsoft's HeapFree() to mark freed heap memory
That is, the problem comes up from the fact that the code deals with released memory as if it is still alive. To isolate the issue to specific code fragment, debug and use call stack information at the time of exception.

Related

Dear IMGUI and DirectX 12 Overlay (DXGI_ERROR_INVALID_CALL)

I'm trying to make a simple frame counter for DirectX 12 games using Dear IMGUI. I simply want to overlay a small transparent window that displays the sequential order of frames during gameplay. To do so, I hook Present(), so I can get the SwapChain, and count the number of times the method is called (frame counting). THIS IS NOT FOR A CHEAT. I am not writing cheats for games, I simply want to record frame numbers for analytical purposes.
I have successfully done this for DirectX 11 using the ShowExampleAppSimpleOverlay() example provided in here: https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp
Here is an image sample showing the frame counter in a DX 11 game.
I'm now trying to do the same with DirectX 12. Hooking the Present() is not an issue.
Using example code provided here: https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx12/main.cpp
I attempt to use the ShowExampleAppSimpleOverlay() method again, however in my code on the call to d3d12CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&d3d12CommandList); (to render the overlay) it results in an error saying (0x887A0001: DXGI_ERROR_INVALID_CALL). This is the last line of code in the code sample provided below:
I'm not sure how to proceed. Any thoughts?
Edit: I forgot to mention that I'm also hooking and acquiring the games command que. So d3d12CommandQueue is acquired directly from the game. It doesn't return NULL so I'm assuming it is the correct object. I could be wrong though...
For each call to Present() do the following:
//iterate frame
Frame_Number = Frame_Number + 1;
//Get Device, using IDXGISwapChain3
ID3D12Device* device;
HRESULT gd = pSwapChain->GetDevice(__uuidof(ID3D12Device), (void**)&device);
assert(gd == S_OK);
//Get window handle from swapchain for IMGUI
DXGI_SWAP_CHAIN_DESC sd;
pSwapChain->GetDesc(&sd);
window = sd.OutputWindow;
//Get backbuffers
buffersCounts = sd.BufferCount;
frameContext = new FrameContext[buffersCounts];
D3D12_DESCRIPTOR_HEAP_DESC descriptorImGuiRender = {};
descriptorImGuiRender.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
descriptorImGuiRender.NumDescriptors = buffersCounts;
descriptorImGuiRender.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
// Create Descriptor Heap IMGUI render
if (device->CreateDescriptorHeap(&descriptorImGuiRender, IID_PPV_ARGS(&d3d12DescriptorHeapImGuiRender)) != S_OK)
return false;
//Create Command Allocator
ID3D12CommandAllocator* allocator;
if (device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&allocator)) != S_OK)
return false;
for (size_t i = 0; i < buffersCounts; i++) {
frameContext[i].commandAllocator = allocator;
}
if (device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, NULL, IID_PPV_ARGS(&d3d12CommandList)) != S_OK ||
d3d12CommandList->Close() != S_OK)
return false;
//create descriptor heap, describe and create a render target view (RTV) descriptor heap.
D3D12_DESCRIPTOR_HEAP_DESC descriptorBackBuffers;
descriptorBackBuffers.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
descriptorBackBuffers.NumDescriptors = buffersCounts;
descriptorBackBuffers.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
descriptorBackBuffers.NodeMask = 1;
if (device->CreateDescriptorHeap(&descriptorBackBuffers, IID_PPV_ARGS(&d3d12DescriptorHeapBackBuffers)) != S_OK)
return false;
const auto rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
// Create frame resources.
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = d3d12DescriptorHeapBackBuffers->GetCPUDescriptorHandleForHeapStart();
// Create a RTV for each frame.
for (size_t i = 0; i < buffersCounts; i++) {
ID3D12Resource* pBackBuffer = nullptr;
frameContext[i].main_render_target_descriptor = rtvHandle;
pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
device->CreateRenderTargetView(pBackBuffer, nullptr, rtvHandle);
frameContext[i].main_render_target_resource = pBackBuffer;
rtvHandle.ptr += rtvDescriptorSize;
}
// Setup Platform/Renderer bindings dor IMGUI
ImGui_ImplWin32_Init(window);
ImGui_ImplDX12_Init(device, buffersCounts,
DXGI_FORMAT_R8G8B8A8_UNORM, d3d12DescriptorHeapImGuiRender,
d3d12DescriptorHeapImGuiRender->GetCPUDescriptorHandleForHeapStart(),
d3d12DescriptorHeapImGuiRender->GetGPUDescriptorHandleForHeapStart());
ImGui::GetIO().ImeWindowHandle = window;
// Start the Dear ImGui frame
ImGui_ImplDX12_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
//call imgui menues here
bool bShow = true;
ShowExampleAppSimpleOverlay(&bShow);
// Rendering (imgui)
FrameContext& currentFrameContext = frameContext[pSwapChain->GetCurrentBackBufferIndex()];
currentFrameContext.commandAllocator->Reset();
D3D12_RESOURCE_BARRIER barrier;
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = currentFrameContext.main_render_target_resource;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
d3d12CommandList->Reset(currentFrameContext.commandAllocator, nullptr);
d3d12CommandList->ResourceBarrier(1, &barrier);
d3d12CommandList->OMSetRenderTargets(1, &currentFrameContext.main_render_target_descriptor, FALSE, nullptr);
d3d12CommandList->SetDescriptorHeaps(1, &d3d12DescriptorHeapImGuiRender);
ImGui::Render();
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), d3d12CommandList);
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
d3d12CommandList->ResourceBarrier(1, &barrier);
d3d12CommandList->Close();
d3d12CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&d3d12CommandList);
DXGI_ERROR_INVALID_CALL tells that one command in the list is invalid but not which.
you need to use the d3d12 debug layer for runtime checks at command list creation.
The debug layer also tell you the reason why it is invalid.
see msdn for more info.
you can aktivate it with the following code, but it needs to be called before device creation
ID3D12Debug* debugInterface;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)))) {
debugInterface->EnableDebugLayer();
}

warning C6262: Function uses '27688' bytes of stack: exceeds /analyze:stacksize '16384'. Consider moving some data to heap

I have read a few questions and topics on this issue. For example:
Warning message regarding stack size
But I can't really work out how I am to isolate the issue in the method:
void CCreateReportDlg::ReadOptions()
{
CHeadingsDlg dlgHeadings(this);
COptionsDlg dlgOptions(this);
CBrothersDlg dlgBrothers(this, FALSE);
CAutoAssignSettingsDlg dlgAssign(this);
CString strSection = theApp.GetActiveScheduleSection(_T("Options"));
// headings
m_strReportTitle = dlgHeadings.GetReportTitle();
dlgHeadings.GetHeadings(m_aryStrHeading);
m_eReportMode = dlgOptions.GetReportMode();
// brother data
dlgBrothers.GetBrotherData(SOUND, m_aryStrSoundWT, m_aryStrSoundSM, TRUE);
dlgBrothers.GetBrotherData(PLATFORM, m_aryStrPlatformWT, m_aryStrPlatformSM, TRUE);
dlgBrothers.GetBrotherData(MIKE, m_aryStrMikeWT, m_aryStrMikeSM, TRUE);
dlgBrothers.GetBrotherData(ATTENDANT, m_aryStrAttendWT, m_aryStrAttendSM, TRUE);
dlgBrothers.GetBrotherData(SOUND, m_aryStrBroSoundAll, TRUE);
dlgBrothers.GetBrotherData(PLATFORM, m_aryStrBroPlatformAll, TRUE);
dlgBrothers.GetBrotherData(MIKE, m_aryStrBroMikeAll, TRUE);
dlgBrothers.GetBrotherData(ATTENDANT, m_aryStrBroAttendAll, TRUE);
CCustomAssignManagerDlg::GetCustomAssignData(m_aryPtrAssign, TRUE, ASSIGN_SORT_HEADING);
if(m_eReportMode != MODE_MEETING)
{
// We need to update the arrays to only include the brothers that are available
// on both days (so the two arrays become identical)
ModifyBrotherArrays();
}
dlgBrothers.GetBrotherData(m_cbBrother);
// We need an array of unique names
// (without first to entries in combo)
// Used during printing and exporting (multi highlight)
dlgBrothers.GetBrotherData(m_aryStrNames);
CBrothersDlg::SortArray(m_aryStrNames);
// options
m_bExcludePlatformColumn = dlgOptions.ExcludePlatformColumn();
m_bExcludePlatformMikeColumn = dlgOptions.ExcludePlatformMikeColumn();
m_bExcludeAttendColumn = dlgOptions.ExcludeAttendantColumn();
m_iNumMikeUsers = dlgOptions.GetNumMikeUsers();
m_iNumSoundUsers = dlgOptions.GetNumSoundUsers();
m_iNumAttendUsers = dlgOptions.GetNumAttendants();
dlgOptions.GetMeetingDays(m_iDayWT, m_iDaySM, m_iDayWeek);
m_iDayWT++;
m_iDaySM++;
m_iDayWeek++;
dlgOptions.GetCustomDateOptions(m_bCustomDate, m_strDateFormat);
m_bAvoidBack2Back = dlgAssign.AvoidBack2Back();
m_bCheckForConflicts = dlgAssign.CheckForConflicts();
m_bSelectNames = dlgAssign.SelectNames();
theApp.ReadDateMapData(m_mapSPtrBroDates);
m_bShowNotes = (BOOL)theApp.GetNumberSetting(strSection, _T("ShowNotes"), (int)TRUE);
m_bNoticeBoard = (BOOL)theApp.GetNumberSetting(strSection, _T("NoticeBoard"), (int)FALSE);
dlgOptions.ReadAssignStatesInfoEx(m_byAryAutoAssignStates);
}
I know I can adjust the compiler and increase the stacksize to supress the error.
But what is the basic approach to identifying the route cause in my method?
The first bunch of variables are CStringArray. Then it is followed by a CPtrArray of objects, of type CUSTOM_ASSIGN_S:
typedef struct tagCustomAssignment
{
int iIndex;
CString strDescription;
CString strHeading;
BOOL bExcluded;
CStringArray aryStrBrothersAll;
CStringArray aryStrBrothersWT;
CStringArray aryStrBrothersSM;
BOOL bIncludeWT;
BOOL bIncludeTMS;
BOOL bFixed;
int iFixedType;
} CUSTOM_ASSIGN_S;
Again, none of the members of the above structure are large arrays [xxx]. The only other notable method is ReadDateMapData that reads an archive and fills another map.
But as mentioned, I don't know how to go about isolating the issue. There are no large arrays being define. One or two TCHAR file[_MAXPATH]; but that is about it. The rest of classes like CStringArray or CPtrArray etc..
Thank you in advance.
Update
Based on the comments provided I was able to establish that even just the variable declarations at the top:
CHeadingsDlg dlgHeadings(this);
COptionsDlg dlgOptions(this);
CBrothersDlg dlgBrothers(this, FALSE);
CAutoAssignSettingsDlg dlgAssign(this);
CString strSection = theApp.GetActiveScheduleSection(_T("Options"));
Would cause it to have a stack size of 18072 to begin with.
My main variables in this class were actually dialog objects which understandably are quite large due to all the member variables etc..
The reason I was using these dialogues was to gain access to application settings by using their public methods.
By changing these dialogue declarations to new / delete and adjusting the code I no longer get the stack size warning:
void CCreateReportDlg::ReadOptions()
{
CHeadingsDlg *pDlgHeadings = new CHeadingsDlg(this);
if (pDlgHeadings != NULL)
{
m_strReportTitle = pDlgHeadings->GetReportTitle();
pDlgHeadings->GetHeadings(m_aryStrHeading);
delete pDlgHeadings;
}
COptionsDlg *pDlgOptions = new COptionsDlg(this);
if (pDlgOptions != NULL)
{
m_eReportMode = pDlgOptions->GetReportMode();
m_bExcludePlatformColumn = pDlgOptions->ExcludePlatformColumn();
m_bExcludePlatformMikeColumn = pDlgOptions->ExcludePlatformMikeColumn();
m_bExcludeAttendColumn = pDlgOptions->ExcludeAttendantColumn();
m_iNumMikeUsers = pDlgOptions->GetNumMikeUsers();
m_iNumSoundUsers = pDlgOptions->GetNumSoundUsers();
m_iNumAttendUsers = pDlgOptions->GetNumAttendants();
pDlgOptions->ReadAssignStatesInfoEx(m_byAryAutoAssignStates);
pDlgOptions->GetCustomDateOptions(m_bCustomDate, m_strDateFormat);
pDlgOptions->GetMeetingDays(m_iDayWT, m_iDaySM, m_iDayWeek);
m_iDayWT++;
m_iDaySM++;
m_iDayWeek++;
delete pDlgOptions;
}
CBrothersDlg *pDlgBrothers = new CBrothersDlg(this, FALSE);
if (pDlgBrothers != NULL)
{
pDlgBrothers->GetBrotherData(SOUND, m_aryStrSoundWT, m_aryStrSoundSM, TRUE);
pDlgBrothers->GetBrotherData(PLATFORM, m_aryStrPlatformWT, m_aryStrPlatformSM, TRUE);
pDlgBrothers->GetBrotherData(MIKE, m_aryStrMikeWT, m_aryStrMikeSM, TRUE);
pDlgBrothers->GetBrotherData(ATTENDANT, m_aryStrAttendWT, m_aryStrAttendSM, TRUE);
pDlgBrothers->GetBrotherData(SOUND, m_aryStrBroSoundAll, TRUE);
pDlgBrothers->GetBrotherData(PLATFORM, m_aryStrBroPlatformAll, TRUE);
pDlgBrothers->GetBrotherData(MIKE, m_aryStrBroMikeAll, TRUE);
pDlgBrothers->GetBrotherData(ATTENDANT, m_aryStrBroAttendAll, TRUE);
pDlgBrothers->GetBrotherData(m_cbBrother);
// We need an array of unique names (without first two entries in combo)
// Used during printing and exporting (multi highlight)
pDlgBrothers->GetBrotherData(m_aryStrNames);
CBrothersDlg::SortArray(m_aryStrNames);
delete pDlgBrothers;
}
CAutoAssignSettingsDlg *pDlgAssign = new CAutoAssignSettingsDlg(this);
if (pDlgAssign != NULL)
{
m_bAvoidBack2Back = pDlgAssign->AvoidBack2Back();
m_bCheckForConflicts = pDlgAssign->CheckForConflicts();
m_bSelectNames = pDlgAssign->SelectNames();
delete pDlgAssign;
}
CCustomAssignManagerDlg::GetCustomAssignData(m_aryPtrAssign, TRUE, ASSIGN_SORT_HEADING);
if(m_eReportMode != MODE_MEETING)
{
// We need to update the arrays to only include the brothers that are available
// on both days (so the two arrays become identical)
ModifyBrotherArrays();
}
theApp.ReadDateMapData(m_mapSPtrBroDates);
CString strSection = theApp.GetActiveScheduleSection(_T("Options"));
m_bShowNotes = (BOOL)theApp.GetNumberSetting(strSection, _T("ShowNotes"), (int)TRUE);
m_bNoticeBoard = (BOOL)theApp.GetNumberSetting(strSection, _T("NoticeBoard"), (int)FALSE);
}

Importing DLL's doesn't work the same (VS2003 to VS2010, multithreaded to multithreaded DLL)

During a massive code update from a mix of VC6, VS2003, and VS2005, I am running into a problem where VS2010 doesn't behave like VS2003 did. The application will scan a directory of DLL's and attempt to load them in one by one. This is done here:
CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName)
{
ASSERT(szPluginName);
ASSERT(AfxIsValidString(szPluginName));
m_csFullpath = szPluginName;
m_hModule = LoadLibrary(m_csFullpath);
m_pInterface = (IConfigDllInterface *) NULL;
pInterface pPtr = pInterface(NULL);
if (m_hModule != NULL)
{
// If we loaded the DLL get the interface pointer
pPtr = pInterface(GetProcAddress(m_hModule, "GetInterface"));
}
if (pPtr != NULL)
{
pPtr(&m_pInterface);
}
else
{
::FreeLibrary(m_hModule);
m_hModule = HMODULE(NULL);
}
}
All DLL's show as being loaded:
...
'GenConfig.exe': Loaded 'C:\src\Debug\config\GenLogonConfig.dll', Symbols loaded.
'GenConfig.exe': Loaded 'C:\src\Debug\config\GenReportConfig.dll', Symbols loaded.
'GenConfig.exe': Loaded 'C:\src\Debug\config\ImportConfig.dll', Symbols loaded.
...
Each DLL has an identical GetInterface implementation shown below:
CConfigDllInterfaceImpl<CParentDlg> gdllObj;
BOOL GetInterface(IConfigDllInterface **ppPtr)
{
*ppPtr = &gdllObj;
// Temporary edit to test if gdllObj is set to proper parent.
CString name;
name = gdllObj.GetDisplayName();
// End edit
return true;
}
With a template as shown below:
__declspec(selectany) UINT guiAdvise;
template <class T> class CConfigDllInterfaceImpl : public IConfigDllInterface
{
public:
CConfigDllInterfaceImpl()
{
guiAdvise = RegisterWindowMessage(_T("GenConfig"));
m_pDlg = NULL;
}
virtual LPCTSTR GetDisplayName() const
{
static CString csTemp;
csTemp.LoadString(IDS_DISPLAY_NAME);
return csTemp;
}
// Can't be virtual because it uses the template T argument
BOOL DoModal(HWND hParent)
{
ASSERT(IsWindow(hParent));
if (m_pDlg == (T *) NULL)
{
m_pDlg = new T(CWnd::FromHandle(hParent));
return m_pDlg->Create();
}
else if (IsWindow(m_pDlg->GetSafeHwnd()))
{
m_pDlg->PostMessage(guiAdvise, eAdviseSwitchViews);
m_pDlg->SetActiveWindow();
}
return TRUE;
} // SNIP...
I can tell that my template isn't properly registering to its intended parent. GetDisplayName just returns "". My suspicion the cause of my problem is that I made a decision a month ago to change everything to Multithreaded DLL from Multithreaded. These are all MFC projects and it seemed the simplest and easiest way to just use _AFXDLL and make everything properly compile and link. All of the rest of my projects work fine, but I believe that because of the way this DLL is loaded:
CConfigDllInterfaceImpl gdllObj;
No longer works the way it used to.
So, question 1: Is my suspicion correct? Or am I completely offbase?
Question 2: If my suspicion is correct, how do I work around this? It isn't an option to go back to multithreaded at this point.
Thanks in advance.
I finally have some time to get back to answering this. Collin Dauphinee was correct in that it was a resource issue. I don't know why VS2003 is different from VS2010, but the solution was very simple.
CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName)
{
ASSERT(szPluginName);
ASSERT(AfxIsValidString(szPluginName));
// Save off current Afx resource handle.
HINSTANCE hCurrentAfx = AfxGetResourceHandle(); // <--- Didn't need to
// do this before.
m_csFullpath = szPluginName;
m_hModule = NULL;
m_hModule = LoadLibrary(m_csFullpath);
m_pInterface = (IConfigDllInterface *) NULL;
pInterface pPtr = pInterface(NULL);
if (m_hModule != NULL)
{
AfxSetResourceHandle(m_hModule); // <--- here is where the resources
// get properly set. This is the
// solution to the problem.
// If we loaded the DLL get the interface pointer
pPtr = pInterface(GetProcAddress(m_hModule, "GetInterface"));
}
if (pPtr != NULL)
{
pPtr(&m_pInterface);
}
else
{
::FreeLibrary(m_hModule);
m_hModule = HMODULE(NULL);
}
// Now put Afx back.
AfxSetResourceHandle(hCurrentAfx);
}
I hope this helps someone else. I was stuck for days on this one.

Memory leak in CLucene

I am using CLucene for creating indexing and searching. The index files created are of more than 5 GB. I have Created the seperate dll for CLucene search.
DLL constructor contains the following code
lucene::index::IndexReader ptrIndexReader;
lucene::search::IndexSearcher searcher; these are defined in class decalaration/
ptrIndexReader = IndexReader::open(pDir.c_str(),false,NULL);
searcher = new IndexSearcher(ptrIndexReader);
I use one search function whose code is as follows
bool LuceneWrapper::SearchIndex(wstring somevalue)
{
lucene::analysis::KeywordAnalyzer fAnalyzer;
Document doc = NULL;
Hits hits = NULL;
Query f_objQuery = NULL;
NistRecord *f_objRecords = NULL;
bool flag = false;
try{
if (ptrIndexReader == NULL)
{
return NULL;
}
// Initialize IndexSearcher
wstring strQuery = _T("+somename:") + somevalue;
// Initialize Query Parser, with Keyword Analyzer
QueryParser *parser = new QueryParser( _T(""),&fAnalyzer);
// Parse Query string
f_objQuery = parser->parse(strQuery.c_str());
// Search Index directory
hits = searcher->search(f_objQuery);
//searcher.
int intHitCount = 0;
intHitCount = hits->length;
if(intHitCount > 0)
{
if(doc!=NULL)
delete [] doc;
flag = true;
}
//searcher.close();
}
catch(CLuceneError& objExp)
{
if(doc!=NULL)
delete doc;
return false;
}
if(hits!=NULL)
delete hits;
if(f_objQuery!=NULL)
delete f_objQuery;
return flag ;
}
I am searching very large number of values. according to the record count the main memory goes high and high and at on level it goes near to 2 GB and application crashes. Can anybody tell me what is wrong with this? Why is memory going so high and application crashing?
You never deallocate parser.
I can't see a reason to allocate it dynamically.
Why don't you just say
QueryParser parser( _T(""), &fAnalyzer);
f_objQuery = parser.parse(strQuery.c_str());
You also need to make sure that you delete both f_objQuery and hits in the event of an exception.
std::unique_ptr can help you here, if you have access to it.
(And you don't have to test for NULL so much - it's OK to delete a null pointer.)

Segmentation fault occurs only under release configuration

For some odd reason, my application likes to break on me when I switch to release and run it outside of my debugger. Here's what works for me, and here's what doesn't
(Qt Creator is the IDE)
Debugging with debug configuration - ok
Running with debug configuration - ok
Debugging with release configuration - ok
Running with release configuration - application crash
My UI is one project, and the core for some stuff as a separate dependency. On Windows (compiling with MSVCC), I hit a menu button, which eventually calls down to a function. In that function, the app breaks on adding a new element to a vector. e.g:
str *x = new str();
str *y = new str();
/* ...set some of x & y's members... */
vector.push_back(x); // works fine
vector.push_back(y); // causes crash
If I comment out the line vector.push_back(y);, the app continues no problem until the app leaves the event scope (i.e. the end of OnMenuButtonClick). On OS X, it's similar to the issue of adding an element to a vector, except I have:
std::vector<foo *> SomeFunction()
{
std::vector<foo *> returningVector;
/* do stuff */
std::vector<foo *> goo = GetFooObjects();
for (int i = 0; i < goo.size(); i++)
{
returningVector.push_back(goo[i]); // breaks here
}
}
So what are some causes of this strange behavior without a debugger attached and not under debug configuration? I've checked to make sure all of my variables are initialized, so I'm stumped. If you want to view the code above, the first part can be located here, and the second part here. Please forgive anything you see as "bad", and if you have suggestions that you just can't contain, then please do message me on GitHub.
Edit:
I looked more into it, and found out exactly what's causing the problem, but don't know how to fix it. This is the function where my app crashes (on OS X):
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
vector<Drive *> Return;
if (HardDisks)
{
vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();
for (int i = 0; i < (int)Disks.size(); i++)
{
DISK_DRIVE_INFORMATION ddi = Disks.at(i);
// First, try reading the disk way
Streams::xDeviceStream* DS = NULL;
try
{
char path[0x200] = {0};
wcstombs(path, ddi.Path, wcslen(ddi.Path));
DS = new Streams::xDeviceStream(ddi.Path);
}
catch (xException& e)
{
continue;
}
if (DS == NULL || DS->Length() == 0 || DS->Length() < HddOffsets::Data)
{
// Disk is not of valid length
continue;
}
DS->SetPosition(HddOffsets::Data);
// Read the FATX partition magic
int Magic = DS->ReadInt32();
// Close the stream
DS->Close();
// Compare the magic we read to the *actual* FATX magic
if (Magic == FatxMagic)
{
Drive *d = new Drive(Disks.at(i).Path, Disks.at(i).FriendlyName, false);
Return.push_back(d);
}
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < (int)LogicalDisks.size(); i++)
{
Return.push_back(LogicalDisks.at(i));
}
return Return;
}
If I change if (HardDisks) to if (HardDisks = false), the app works just fine. So, I looked into that scope and discovered that after vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();, the heap gets corrupt or something like that. I noticed this because in the debugger, after that function is called, my HardDisks bool changes to "false", which wasn't what it was before.
Here is GetPhysicalDisks:
vector<Drive::DISK_DRIVE_INFORMATION> Drive::GetPhysicalDisks( void )
{
// RIGHT AFTER this vector is initialized, everything goes to hell
vector<Drive::DISK_DRIVE_INFORMATION> ReturnVector;
DIR *dir;
dirent *ent;
dir = opendir("/dev/");
if (dir != NULL)
{
// Read the shit
while ((ent = readdir(dir)) != NULL)
{
// Check the directory name, and if it starts with "disk" then keep it!
QRegExp exp("disk*");
exp.setPatternSyntax(QRegExp::Wildcard);
exp.setCaseSensitivity(Qt::CaseInsensitive);
if (exp.exactMatch(ent->d_name))
{
DISK_DRIVE_INFORMATION curdir;
memset(curdir.FriendlyName, 0, sizeof(curdir.FriendlyName));
memset(curdir.Path, 0, sizeof(curdir.Path));
char diskPath[0x50] = {0};
sprintf(diskPath, "/dev/r%s", ent->d_name);
mbstowcs(curdir.Path, diskPath, strlen(diskPath));
int device;
if ((device = open(diskPath, O_RDONLY)) > 0)
{
#ifdef __linux
hd_driveid hd;
if (!ioctl(device, HDIO_GET_IDENTITY, &hd))
{
swprintf(curdir.FriendlyName, strlen(hd) * 2, L"%hs", hd.model);
}
#elif defined __APPLE__
mbstowcs(curdir.FriendlyName, ent->d_name, strlen(ent->d_name));
#endif
ReturnVector.push_back(curdir);
}
}
}
}
return ReturnVector;
}
While this isn't a real answer as to what happened, I did find a way to fix the problem. Looking at my edit above, I edited my Drive::GetFATXDrives function like so:
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
// Initialize Disks vector up here
vector<DISK_DRIVE_INFORMATION> Disks;
// Call the function to get the hard disks
if (HardDisks)
Drive::GetPhysicalDisks(Disks);
vector<Drive *> ReturnVector;
if (HardDisks)
{
Streams::xDeviceStream* DS = NULL;
for (int i = 0; i < (int)Disks.size(); i++)
{
/* ... */
}
if (DS)
{
DS->Close();
delete DS;
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < LogicalDisks.size(); i++)
{
ReturnVector.push_back(LogicalDisks[i]);
}
return ReturnVector;
}
And my Drive::GetPhysicalDisks function now takes a vector<DISK_DRIVE_INFORMATION> reference instead of returning one. Seemed to make my program work just fine after that.