|
FINALLY
I MADE IT
|
|
|
|
|
Hi
I am getting a heap corruption. I am running under the visual studio debugger. and the exception is at Quote:
ntdll.dll!RtlReportCriticalFailure() Unknown
My scenario is I have a DLL reading and formatting data for a .exe. I keep a record count so when I get a exception, at Quote: ntdll.dll!RtlReportCriticalFailure() Unknown
I insert code if (recordcount == 0x0000196e) __debugbreak; I then start stepping through the code looking for the problem how ever when stepping through the code works I try this multiple times however when I stop the code where the exception were to occur it always complete successfully
The listing I am trying to to inset in the richedit is huge about 153 pages 30 lines to page, 134 bytes across I roughly calculate the number of bytes I am trying to insert into the richedit is 1.6 meg. I am not sure if the size is the issue I do a Rciheditctrl::LimitText with the amount bytes I need
Again when break on the offending record and step thru the code it completes normally
Here is the stack frame My code starts a the DriveRichedit.exe
ntdll.dll!RtlReportCriticalFailure() Unknown
ntdll.dll!RtlpHeapHandleError() Unknown
ntdll.dll!RtlpHpHeapHandleError() Unknown
ntdll.dll!RtlpLogHeapFailure() Unknown
ntdll.dll!RtlpHeapFindListLookupEntry() Unknown
ntdll.dll!RtlpFindEntry() Unknown
ntdll.dll!RtlpAllocateHeap() Unknown
ntdll.dll!RtlpAllocateHeapInternal() Unknown
riched20.dll!CTxtArray::AddBlock(long,long) Unknown
riched20.dll!CTxtArray::SplitBlock(long,long,long,long,int) Unknown
riched20.dll!CTxtPtr::InsertRange(long,unsigned short const *) Unknown
riched20.dll!CRchTxtPtr::ReplaceRange(long,long,unsigned short const *,class IUndoBuilder *,long,long *,unsigned long) Unknown
riched20.dll!CTxtRange::ReplaceRange(long,unsigned short const *,class IUndoBuilder *,enum SELRR,long *,unsigned long) Unknown
riched20.dll!CTxtRange::CheckLimitReplaceRange(long,unsigned short const *,int,class IUndoBuilder *,unsigned long,long *,long,int,unsigned long) Unknown
riched20.dll!CTxtRange::CleanseAndReplaceRange(long,unsigned short const *,int,class IUndoBuilder *,unsigned short *,long *,unsigned long) Unknown
riched20.dll!CLightDTEngine::ReadPlainText(class CTxtRange *,struct _editstream *,int,class IUndoBuilder *,long) Unknown
riched20.dll!CLightDTEngine::LoadFromEs(class CTxtRange *,long,struct _editstream *,int,class IUndoBuilder *) Unknown
riched20.dll!CTxtEdit::TxSendMessage(unsigned int,unsigned __int64,__int64,__int64 *) Unknown
riched20.dll!RichEditWndProc() Unknown
riched20.dll!RichEditANSIWndProc() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW(__int64 ,struct HWND__ *,enum _WM_VALUE,unsigned __int64,__int64,int) Unknown
user32.dll!CallWindowProcA() Unknown
mfc140d.dll!CWnd::DefWindowProcA(unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 1100 C++
mfc140d.dll!CWnd::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 2100 C++
mfc140d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 265 C++
mfc140d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 418 C++
mfc140d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 299 C++
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!SendMessageWorker() Unknown
user32.dll!SendMessageInternal(struct HWND__ *,unsigned int,unsigned __int64,__int64,int) Unknown
user32.dll!SendMessageA() Unknown
mfc140d.dll!CRichEditCtrl::StreamIn(int nFormat, _editstream & es) Line 775 C++
> DriveRichEdit.exe!CProgDebug::OnInitDialog() Line 136 C++
[External Code]
DriveRichEdit.exe!CMainFrame::PROGDEBUG() Line 48 C++
[External Code]
DriveRichEdit.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 26 C++
[External Code]
|
|
|
|
|
I am curios, are you using the MFC code in a Managed C++/CLI application?
|
|
|
|
|
I’m not apparently I posted in the wrong forum I meant to post in the MFC forum
|
|
|
|
|
Hi
I have been looking at the examples off dll and TLS
First thing I noticed that
DWORD g_dwThreadIndex; is in global storage
It would be nice as in the IBM manuals would have registers on at entry to DllMain
I mean is the SP (register) that of the calling application
regardless if the index returned from tlsalloc lets say is 5
and then before the current thread access the storage set by tlssetvalue
another thread does a tlsallloc g_dwThreadindex becomes 6
then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something
I mean if gw_dwThreadindex would be defined in the callers stack I would get it
more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo
|
|
|
|
|
We don't know which examples you've been looking at. But the whole point of thread-local storage is that it's local to the thread; one thread cannot modify a TLS variable for another thread. (At least not without jumping through several flaming hoops whilst drenched in LPG and holding a large firework.)
Each thread gets its own copy of the TLS variable. If thread A set it to 5, and thread B sets it to 6, thread A will still see it set to 5.
Thread Local Storage | Microsoft Learn[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I am refering to the following example i found in the codeproject my lack of understanding is due to the fact that gw_dwThreadIndexis defined in global storage not stack/local storage
Shrink ▲
struct ThreadData {
};
...
DWORD g_dwThreadIndex;
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD dwReason, LPVOID )
{
ThreadData* pData;
switch (dwReason) {
case DLL_PROCESS_ATTACH:
g_dwThreadIndex = ::TlsAlloc();
if (g_dwThreadIndex == TLS_OUT_OF_INDEXES)
return FALSE;
case DLL_THREAD_ATTACH:
pData = (ThreadData*) ::LocalAlloc(LPTR, sizeof(ThreadData));
if (pData == 0)
return FALSE;
::TlsSetValue(g_dwThreadIndex, (LPVOID) pData);
break;
case DLL_THREAD_DETACH:
pData = (ThreadData*) ::TlsGetValue(g_dwThreadIndex);
if (pData != 0)
::LocalFree((HLOCAL) pData);
break;
case DLL_PROCESS_DETACH:
pData = (ThreadData*) ::TlsGetValue(g_dwThreadIndex);
if (pData != 0)
::LocalFree((HLOCAL) pData);
::TlsFree(g_dwThreadIndex);
break;
}
return TRUE;
}
...
};
|
|
|
|
|
I'm not a C++ person, but as far as I can see, the only place you write to the g_dwThreadIndex variable is in the DLL_PROCESS_ATTACH code. According to Microsoft, that means:
The DLL is being loaded into the virtual address space of the current process as a result of the process starting up or as a result of a call to LoadLibrary . DLLs can use this opportunity to initialize any instance data or to use the TlsAlloc function to allocate a thread local storage (TLS) index.
As far as I can see, that will only ever happen once per process. And the documentation explicitly says that this is the correct time to call TlsAlloc .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Just realized posted to wrong forum however the variable is in static or global storage the next thread that comes by can change its value thats my problem just about all the. examples for TLS and DLL s have it this way
|
|
|
|
|
ForNow wrote: the next thread that comes by can change its value
Well yes, if you do it wrong you can shoot yourself in the foot.
As far as I can see, the example you're looking at is not doing it wrong. The global variable is initialized once, in the place where the documentation says it should be initialized.
This seems to be a case of "if I stick a fork in my toaster whilst it's switched on, I can get an electric shock; therefore, all toasters are dangerous and should be banned".
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
This example works if the DLL is servicing only one address space but if it’s system DLL than I think there would be a problem ?
|
|
|
|
|
I'm not sure I quite understand what you are asking, but each thread gets its own stack (pointed at by SP) which provides all the thread local storage. It can also allocate its own storage through the normal methods. You have not really explained what g_dwThreadIndex is being used for in relation to the question. Does this all relate to some article, or specific MSDN page?
|
|
|
|
|
Richard I think I’m begging to understand the source of my confusion
First it is my understanding there are Two types off DLL one for the entire operating system in my case windows 10 and one servicing threads of one address space if it’s the former I mean that works like USER.DLL then the code example of tls wouldn’t work an I right in this ?
|
|
|
|
|
No there is only one type of DLL, which is a Dynamically Loadable Library. However, it may, or may not, be thread safe, depending on how it is created. Most (all?) of the Windows provided DLLs are thread safe. And the whole point of having DLLs is that the system only needs to load it once, to service multiple executables (i.e. address spaces). Be that as it may, I am still not sure what your concern is with regard to threads.
|
|
|
|
|
I’m sure you are right ( or else nothing would work )
I think what I have to do is have 2 exe both load the same DLL run under it under visual studio debugger and look at the address thanks
|
|
|
|
|
The actual source of the code referenced
Using Thread Local Storage in a Dynamic-Link Library - Win32 apps | Microsoft Learn[^]
Following is also relevant to see the messages.
DllMain entry point (Process.h) - Win32 apps | Microsoft Learn[^]
The code example is skipping the normal TLS semantics. So in other words it is using the first TLS index for all storage. Within the code provided.
This might follow into the following comment...
ForNow wrote: and then before the current thread access the storage set by tlssetvalue
another thread does a tlsallloc g_dwThreadindex becomes 6
Not exactly sure what you are saying there but I think you are presuming that somehow this initialization code is not thread safe. In that it might be called by multiple threads at the same time. This code method will never be called by more than one thread at a time. Additionally the 'DLL_PROCESS_ATTACH' will never be called more than once (within one process space of course.)
|
|
|
|
|
Hi
I think I’m begging to understand the source of my confusion
It is my understanding there are two types of dll’s
One services the entire os like kerenel.DLL and one just a particular address space if my code is of the former than this example is not PROCESS safe am I correct in my understanding ?
|
|
|
|
|
ForNow wrote: there are two types of dll’s
Sort of true but also not true.
When a dll is loaded the whatever loaded it decides how to use it. In one case the defining characteristic of an 'application' is that it must have a defined entry point and other defined behaviors. That is true for every operating system (not just windows and dlls.)
The code above provides a defined entry point.
Other dlls might just be libraries and they might have many 'entry' points (methods) although how each of those is defined (laid out in the dll) defines whether it can be successfully called and even how it must be called.
All of that is rather esoteric though and is almost never going to be an issue.
|
|
|
|
|
Here's some good news for anyone dealing with C++/CLI:
Stephan Lavavej recently committed changes to the VC STL which will remove a number of the roadblocks and warnings we've hit using C++/CLI in recent years. The rest of our codebase is moving to use C++20 constructs and the /clr code has had problems.
The PR: Enable /clr C++ 20 support #3194
John
|
|
|
|
|
apakah anda bisa membantu saya membuat sebuah program yang sama outputnya tetapi beda kode programnya?
tolong bantu aku
#include <iostream>
#include <string>
using namespace std;
// PROGRAM MENGHILANGKAN KARAKTER YANG SAMA DENGAN REKURSIF
void remove(string roihan){
//BASE CASE
if (roihan.length() == 1){
cout<
|
|
|
|
|
No. Partly because it's incomplete so we have no idea what it's supposed to do, partly because if you are trying to recreate an existing program, it's because the version you have can't be handed in without you presumably getting spotted for plagiarism.
And if that's the case, you won't learn anything from the exercise if you do.
Sit down with your assignment, think about it, and try designing an app from scratch. You end up learning more, and that means that your next assignment will be easier for you to complete yourself.
If you are having problems getting started at all, then this may help: How to Write Code to Solve a Problem, A Beginner's Guide[^]
And by the way: when I told you yesterday that we are an English language site, it's somewhat rude to ignore that and carry on posting in Indonesian. Being rude to people you want voluntary help from isn't a good way to start ...
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
fungsi program adalah menghilangkan karakter yang sama sehingga karakter tersebut hanya munsul satu kali dengan menggunakan rekursif
perogram ku blm sempurnah
Google Translate: the function of the program is to remove the same character so that the character appears only once by using recursive
my program is not perfect
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
char nama[1000];
int index[100];
cout<<"masukkan nama = ";
for(int i=0; i<strlen(nama); i++){
int n=0;
for(int j=0; j<strlen(nama); j++){
if(nama[i] == nama[j]){
n++;
index[j]=i;
}
}
}
for(int i=0; i<strlen(nama); i++){
if(i == index[i]){
cout<<nama[i];
}
}
}
|
|
|
|
|
This is an English language site, and we can only accept and answer questions in that language.
I have run this through Google Translate to produce a probably-good version, but you should check it and make sure it does say what you are actually asking.
And that code isn't recursive: it's iterative.
Recursion happens when a function calls itself, either directly:
int foo(int i)
{
if (i <= 1) return 1;
return i + foo(i - 1);
} Or indirectly:
int foo(int i)
{
if (i <= 1) return 1;
return i + bar(i);
}
int bar(int i)
{
return foo(i - 1);
} Your code contains one method, which you do not call yourself!
And please, do yourself a favour and indent your code more deeply - it's a lot easier to see what is going on with three or four spaces per indent rather than one. It's not a massive problem with a tiny code fragment like you show, but as your code gets bigger it becomes seriously difficult to work out what is going on!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Hi,
I am using vs-2015. Managed C++/Cli Windows Forms Applications. I have Form1-MdiContainer & Form2. From Form1_Button_Click() accessing Form2.
In Form2_Load() I have OLEDBConnection. For When I press Form1-Button_Click(),
First time it's working good. Also when I re-click() the same Form1-Button()
the whole application is getting closed. I analysed that when I close the OLEDBConnection, the whole program is also getting closed. And the same code working good in c#. I can't understand my mistakes..! Thanks.
Note:- For First time when I click the Form1-Button no problem it's working good. But for re-click() whole application is getting closed().
Thanks Again
My Codes
Form1-MdiContainer()
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Form2^ MyStForm = Form2::GetForm(true, this);
MyStForm->MdiParent = this;
MyStForm->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
MyStForm->Dock = DockStyle::Fill;
MyStForm->Show();
}
Form2-Top side
public ref class Form2 : public System::Windows::Forms::Form
{
public: static Form2^ Form2::_instance = nullptr;
public: static Form2^ Form2::GetForm(bool IsMDIChild, System::Windows::Forms::Form^ MyInstFrm) {
if (_instance == nullptr)
_instance = gcnew Form2();
if (_instance->IsDisposed)
_instance = gcnew Form2();
if (IsMDIChild)
_instance->MdiParent = MyInstFrm;
return _instance;
}
blah..blah...blah...
}
Form2-Load()
private: System::Void Form2_Load(System::Object^ sender, System::EventArgs^ e) {
String^ MyStrConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + MyExcelFile + "; Extended Properties=\"Excel 12.0; HDR=YES; OLE DB Services=-1; \"";
String^ MyExcelFile="C:\Students\Names.xlsx";
String^ MyExcelSheet = "[Sheet1$]";
String^ MySQLSelect = "select * from " + MyExcelSheet;
System::Data::OleDb::OleDbConnection^ Cn1 = nullptr;
Cn1 = gcnew System::Data::OleDb::OleDbConnection();
Cn1->ConnectionString = MyStrConn;
System::Data::OleDb::OleDbCommand^ MyCmd = nullptr;
MyCmd = gcnew System::Data::OleDb::OleDbCommand();
MyCmd->CommandText = MySQLSelect;
MyCmd->Connection = Cn1;
Cn1->Open();
System::Data::OleDb::OleDbDataAdapter^ Da1 = gcnew System::Data::OleDb::OleDbDataAdapter(MyCmd);
Da1->Fill(MyDataTable);
Cn1->Close();
if (Cn1 != nullptr){
MyCmd->Cancel();
}
MyCmd = nullptr;
Cn1 = nullptr;
}
Thanks
|
|
|
|
|
This might help re: the data adapter.
Quote: This overload of the Fill method does not implicitly call Close on the ADO object when the fill operation is complete. Therefore, always call Close when you are finished using ADO Recordset or Record objects. This makes sure that the underlying connection to a data source is released in a timely manner, and also prevents possible access violations because of unmanaged ADO objects being reclaimed by garbage collection when existing references still exist.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|