I am creating a view in my project which is a child class of CView.
class CBaseGLView : public CView
In oncreate function I am checking it null or not as below:
int CBaseGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
m_hWnd = GetSafeHwnd();
if( ::IsWindow(m_hWnd)== NULL)
{
return 1;
}
m_pCDC= new CClientDC(this);
m_hDC = m_pCDC->GetSafeHdc();
if (SetWindowPixelFormat()==FALSE)
return 0;
return 0;
}
When I am debugging with ApplicationVerifier I am getting a debug assertion in below lines in afxwin2.inl:
_AFXWIN_INLINE LRESULT CWnd::_AFX_FUNCNAME(SendMessage)(UINT message, WPARAM wParam, LPARAM lParam) const
{ ASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd, message, wParam, lParam); }
And also m_hwnd is shown as unused 0 with the memory address of 0x00170fd6.
Given below is the output from Application verifier.
VERIFIER STOP 00000013: pid 0xDF4: First chance access violation for current stack trace.
339F9020 : Invalid address causing the exception.
0109D75E : Code address executing the invalid access.
0018E034 : Exception record.
0018E084 : Context record.
Following is the call stack of the debug build. It is too long, sorry for that.
ntdll.dll!7729000c()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
vrfcore.dll!VfCoreRedirectedStopMessage(unsigned long Code=19, char * Message=0x73341b5c, unsigned long Param1=444756000, char * Description1=0x73341b94, unsigned long Param2=17422174, char * Description2=0x73341bb4, unsigned long Param3=1630260, char * Description3=0x73341bd4, unsigned long Param4=1630340, char * Description4=0x73341c00) Line 103 + 0x19 bytes C++
vfbasics.dll!VerifierStopMessage(unsigned long Code=19, char * Message=0x73341b5c, unsigned long Param1=444756000, char * Description1=0x73341b94, unsigned long Param2=17422174, char * Description2=0x73341bb4, unsigned long Param3=1630260, char * Description3=0x73341bd4, unsigned long Param4=1630340, char * Description4=0x73341c00) Line 1214 C
vfbasics.dll!AVrfpCheckFirstChanceException(_EXCEPTION_POINTERS * ExceptionPointers=0x0018df7c) Line 1108 + 0x2b bytes C
vfbasics.dll!AVrfpVectoredExceptionHandler(_EXCEPTION_POINTERS * ExceptionPointers=0x0018df7c) Line 323 C
ntdll.dll!772f62de()
ntdll.dll!772db652()
ntdll.dll!772db314()
ntdll.dll!77290133()
user32.dll!753a617a()
Axial.exe!CWnd::SendMessageA(unsigned int message=2125, unsigned int wParam=0, long lParam=0) Line 42 + 0x44 bytes C++
Axial.exe!SECWorkbookClientWnd::OnMDISetMenu(unsigned int wParam=261688291, long lParam=21302363) Line 390 C++
Axial.exe!CWnd::OnWndMsg(unsigned int message=560, unsigned int wParam=261688291, long lParam=21302363, long * pResult=0x0018e980) Line 2018 + 0x11 bytes C++
Axial.exe!CWnd::WindowProc(unsigned int message=560, unsigned int wParam=261688291, long lParam=21302363) Line 1755 + 0x20 bytes C++
Axial.exe!AfxCallWndProc(CWnd * pWnd=0x1a54bf98, HWND__ * hWnd=0x00120ff0, unsigned int nMsg=560, unsigned int wParam=261688291, long lParam=21302363) Line 240 + 0x1c bytes C++
Axial.exe!AfxWndProc(HWND__ * hWnd=0x00120ff0, unsigned int nMsg=560, unsigned int wParam=261688291, long lParam=21302363) Line 403 C++
user32.dll!753962fa()
user32.dll!75397316()
user32.dll!75396ce9()
user32.dll!75396de8()
user32.dll!75396e44()
ntdll.dll!7729010a()
user32.dll!753972b9()
user32.dll!753a2161()
user32.dll!753a0f91()
user32.dll!753a9deb()
user32.dll!753a9dfd()
user32.dll!753a8124()
Axial.exe!CMDIChildWnd::DefWindowProcA(unsigned int nMsg=34, unsigned int wParam=0, long lParam=0) Line 429 C++
Axial.exe!CWnd::WindowProc(unsigned int message=34, unsigned int wParam=0, long lParam=0) Line 1756 + 0x1c bytes C++
Axial.exe!AfxCallWndProc(CWnd * pWnd=0x1a826f08, HWND__ * hWnd=0x00210bbe, unsigned int nMsg=34, unsigned int wParam=0, long lParam=0) Line 240 + 0x1c bytes C++
Axial.exe!AfxWndProc(HWND__ * hWnd=0x00210bbe, unsigned int nMsg=34, unsigned int wParam=0, long lParam=0) Line 403 C++
user32.dll!753962fa()
user32.dll!75396d3a()
user32.dll!75396ce9()
user32.dll!75396de8()
user32.dll!75396e44()
ntdll.dll!7729010a()
user32.dll!75398e63()
user32.dll!753a7b51()
Axial.exe!CFrameWnd::BringToTop(int nCmdShow=1) Line 2362 C++
Axial.exe!CFrameWnd::ActivateFrame(int nCmdShow=1) Line 2341 C++
Axial.exe!CMDIChildWnd::ActivateFrame(int nCmdShow=-1) Line 762 C++
Axial.exe!CFrameWnd::InitialUpdateFrame(CDocument * pDoc=0x1a6a2de8, int bMakeVisible=1) Line 814 C++
Axial.exe!CDocTemplate::InitialUpdateFrame(CFrameWnd * pFrame=0x1a826f08, CDocument * pDoc=0x1a6a2de8, int bMakeVisible=1) Line 330 C++
Axial.exe!CMultiDocTemplate::OpenDocumentFile(const char * lpszPathName=0x0018f6fc, int bMakeVisible=1) Line 166 C++
Axial.exe!CDocManager::OpenDocumentFile(const char * lpszFileName=0x19418fa0) Line 986 C++
Axial.exe!CWinApp::OpenDocumentFile(const char * lpszFileName=0x19418fa0) Line 84 C++
Axial.exe!CAxialApp::OpenDocumentFile(const char * lpszFileName=0x19418fa0) Line 983 + 0xc bytes C++
Axial.exe!CWinApp::OnOpenRecentFile(unsigned int nID=57616) Line 132 + 0x2a bytes C++
Axial.exe!_AfxDispatchCmdMsg(CCmdTarget * pTarget=0x018e6e88, unsigned int nID=57616, int nCode=0, void (void)* pfn=0x009f8140, void * pExtra=0x00000000, unsigned int nSig=60, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 101 + 0xa bytes C++
Axial.exe!CCmdTarget::OnCmdMsg(unsigned int nID=57616, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 381 + 0x27 bytes C++
Axial.exe!CAxialApp::OnCmdMsg(unsigned int id=57616, int code=0, void * extra=0x00000000, AFX_CMDHANDLERINFO * handler=0x00000000) Line 1135 + 0x40 bytes C++
Axial.exe!CFrameWnd::OnCmdMsg(unsigned int nID=57616, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 951 + 0x23 bytes C++
Axial.exe!SECMDIFrameWnd::OnCmdMsg(unsigned int nID=57616, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 2270 C++
Axial.exe!CWnd::OnCommand(unsigned int wParam=57616, long lParam=0) Line 2364 C++
Axial.exe!CFrameWnd::OnCommand(unsigned int wParam=57616, long lParam=0) Line 366 C++
Axial.exe!SECMDIFrameWnd::OnCommand(unsigned int wParam=57616, long lParam=0) Line 2214 + 0x10 bytes C++
Axial.exe!CWnd::OnWndMsg(unsigned int message=273, unsigned int wParam=57616, long lParam=0, long * pResult=0x0018fc68) Line 1769 + 0x1e bytes C++
Axial.exe!CWnd::WindowProc(unsigned int message=273, unsigned int wParam=57616, long lParam=0) Line 1755 + 0x20 bytes C++
Axial.exe!SECMDIFrameWnd::WindowProc(unsigned int message=273, unsigned int wParam=57616, long lParam=0) Line 2685 + 0x14 bytes C++
Axial.exe!AfxCallWndProc(CWnd * pWnd=0x1a4acf78, HWND__ * hWnd=0x0005102a, unsigned int nMsg=273, unsigned int wParam=57616, long lParam=0) Line 240 + 0x1c bytes C++
Axial.exe!AfxWndProc(HWND__ * hWnd=0x0005102a, unsigned int nMsg=273, unsigned int wParam=57616, long lParam=0) Line 403 C++
user32.dll!753962fa()
user32.dll!75396d3a()
user32.dll!75396ce9()
user32.dll!753977c4()
user32.dll!75397bca()
Axial.exe!AfxInternalPumpMessage() Line 183 C++
Axial.exe!CWinThread::PumpMessage() Line 900 C++
Axial.exe!CWinThread::Run() Line 629 + 0xd bytes C++
Axial.exe!CWinApp::Run() Line 896 C++
Axial.exe!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x07e78ffd, int nCmdShow=1) Line 47 + 0xd bytes C++
Axial.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x07e78ffd, int nCmdShow=1) Line 34 C++
Axial.exe!__tmainCRTStartup() Line 263 + 0x2c bytes C
Axial.exe!WinMainCRTStartup() Line 182 C
kernel32.dll!768033aa()
ntdll.dll!772b9ef2()
ntdll.dll!772b9ec5()
Your help is greately appreciated.
Thanks.
It looks like the problem is SECWorkbookClientWnd::OnMDISetMenu. You're probably calling a function that is trying to send a message to a CWnd that is not yet created/attached.
Related
In my sample C program, compiled with gcc, .bss section has an index [24], as shown by readelf -S.
When I try to see the things stored in .bss, by running
readelf -s ./pointer | grep 24, I get
Num: Value Size Type Bind Vis Ndx Name
24: 00000000000040a0 0 SECTION LOCAL DEFAULT 24
31: 00000000000040a8 1 OBJECT LOCAL DEFAULT 24 completed.7392
54: 00000000000040b0 8 OBJECT GLOBAL DEFAULT 24 label
68: 00000000000040c0 0 NOTYPE GLOBAL DEFAULT 24 _end
70: 00000000000040b8 4 OBJECT GLOBAL DEFAULT 24 i
71: 0000000000004090 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
79: 00000000000040ac 4 OBJECT GLOBAL DEFAULT 24 err
81: 00000000000040a0 8 OBJECT GLOBAL DEFAULT 24 stderr##GLIBC_2.2.5
size ./pointer gives me
text data bss dec hex filename
3196 680 32 3908 f44 ./pointer
what's the symbol without any name and symbol with name completed.7392?
and, why size doesn't add up to 32 bytes, as shown by size? [ it is 25 now ]
As a side question, where are stdin and stdout symbols? I can find only stderr, and that is in the bss section.
program source attached below. compiled with gcc version 9.2
/*
* A program that will read and print printable characters in it's memory given a memory address
* until it segfaults
*/
#define _GNU_SOURCE /* Bring REG_XXX names from /usr/include/sys/ucontext.h */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <ucontext.h>
int i,err=0;
void sighandler(int signum);
void* label;
void readmem(){
long loc;
i=0;
err=0;
printf("enter mem location:");
scanf("%lx",&loc);
printf("--dump begin--\n");
char * addr = (void *) loc;
char ch;
label=&&l;
/* was kept there so that I can find how many bytes to increment rip to recover fro segfault
address can be found using gdb also
*/
while(1){
ch=addr[i];
l:
printf("%c",ch);
i++;
if ( err == 1)
break;
// printf("%d\n",i);
}
}
static void sigaction_segv(int signal, siginfo_t *si, void *arg)
{
ucontext_t *ctx = (ucontext_t *)arg;
/* We are on linux x86, the returning IP is stored in RIP (64bit) or EIP (32bit).
In this example, the length of the offending instruction is 6 bytes.
So we skip the offender !
&&l will return address pointed by label l
(gdb) disass readmem
...
0x0000555555555284 <+139>: mov -0x10(%rbp),%rax
0x0000555555555288 <+143>: add %rdx,%rax
=> 0x000055555555528b <+146>: movzbl (%rax),%eax -> rip on segfault
0x000055555555528e <+149>: mov %al,-0x19(%rbp)
0x0000555555555291 <+152>: movsbl -0x19(%rbp),%eax
0x0000555555555295 <+156>: mov %eax,%edi
0x0000555555555297 <+158>: callq 0x555555555030 <putchar#plt>
...
>>
(gdb) p (void*) label
$1 = (void *) 0x555555555291 <readmem+152> ->address of next instruction
>>
we need to go to <readmem+152> ie, next instruction
so we add decimal 6 to rip in sighandler
*/
#if __WORDSIZE == 64
printf("\nCaught SIGSEGV, addr %p, RIP 0x%lx\n",si->si_addr,ctx->uc_mcontext.gregs[REG_RIP]);
ctx->uc_mcontext.gregs[REG_RIP] += 6;
#else
printf("Caught SIGSEGV, addr %p, EIP 0x%x\n",si->si_addr,ctx->uc_mcontext.gregs[REG_EIP]);
ctx->uc_mcontext.gregs[REG_EIP] += 6;
#endif
err=1;
printf("no of bytes read:%d\n",i);
}
int main () {
// 0x0 is hex literal that defaults to signed integer
// here we are casting it to a void pointer
// and then assigning it to a value declared to be a void pointer
// this is the correct way to create an arbitrary pointer in C
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = sigaction_segv;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &sa, NULL) == -1) {
fprintf(stderr, "failed to setup SIGSEGV handler\n");
exit(1);
}
char c[25];
sprintf(c,"cat /proc/%d/maps",getpid());
system(c);
while(1){
readmem();
}
}
I've got a very simple encryption/decryption program that works fine without FIPS support enabled, but fails when it is:
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the decryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
/* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
/* Finalise the decryption. Further plaintext bytes may be written at
* this stage.
*/
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
plaintext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
int main (void)
{
/* Force FIPS initialization */
FIPS_mode_set(1);
/* Set up the key and iv. Do I need to say to not hard code these in a
* real application? :-)
*/
/* A 256 bit key */
unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
/* A 128 bit IV */
unsigned char *iv = (unsigned char *)"01234567890123456";
/* Message to be encrypted */
unsigned char *plaintext =
(unsigned char *)"The quick brown fox jumps over the lazy dog";
/* Buffer for ciphertext. Ensure the buffer is long enough for the
* ciphertext which may be longer than the plaintext, dependant on the
* algorithm and mode
*/
unsigned char ciphertext[128];
/* Buffer for the decrypted text */
unsigned char decryptedtext[128];
int decryptedtext_len, ciphertext_len;
/* Initialise the library */
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
/* Encrypt the plaintext */
ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv,
ciphertext);
/* Do something useful with the ciphertext here */
printf("Ciphertext is:\n");
BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len);
/* Decrypt the ciphertext */
decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv,
decryptedtext);
/* Add a NULL terminator. We are expecting printable text */
decryptedtext[decryptedtext_len] = '\0';
/* Show the decrypted text */
printf("Decrypted text is:\n");
printf("%s\n", decryptedtext);
/* Clean up */
EVP_cleanup();
ERR_free_strings();
return 0;
}
As you can see, just the demo code with FIPS enabled. Without FIPS, my output is:
Ciphertext is:
0000 - e0 6f 63 a7 11 e8 b7 aa-9f 94 40 10 7d 46 80 a1 .oc.......#.}F..
0010 - 17 99 43 80 ea 31 d2 a2-99 b9 53 02 d4 39 b9 70 ..C..1....S..9.p
0020 - 2c 8e 65 a9 92 36 ec 92-07 04 91 5c f1 a9 8a 44 ,.e..6.....\...D
Decrypted text is:
The quick brown fox jumps over the lazy dog
With FIPS, compilation goes fine, but generates the following when run:
139686960322208:error:2D0A0086:FIPS routines:FIPS_cipher:selftest failed:fips_enc.c:336:
139686960322208:error:2D0A0086:FIPS routines:FIPS_cipher:selftest failed:fips_enc.c:336:
I've tried both as a C project, and as a C++ project, pointing the CC env variable at both the fipsld script, and the modified fipsld++ script as appropriate. My FIPSLD_CC variable points to gcc as noted in the FIPS documentation.
What am I missing here?
my code have this error when compiling in Dev-C++.
The error is: [Error] initializer-string for array of chars is too long [-fpermissive]
And part of code is:
struct ffthdr {
char fftc[4]; // .fft
long fftsize; // fft size
long windowsize; // windowsize (<= fftsize)
long hopsize; // hop size (<=fftsize)
long dlength; // original file data length in samples
long srate; // original file sample rate
long winType; // window type
};
void rfft(float *x, long N, int forward);
void cfft(float *x, long NC, int forward);
void bitreverse(float *x, long N);
int makewindow(int aType, float *win, long length);
int dowindow(float *fdata, float *window, long length);
int main(int argc, char *argv[]) {
float *result,*tempres=0,*window=0;
short *data;
float max,norm=1.0;
long i,time,fsize=1024,wsize=512,hsize=256,nread;
int wavein;
long length,srate,winType=1;
FILE *input, *output;
struct soundhdr hdr;
struct ffthdr fhdr = {".fft",1024,512,256,0,0,1};
The erros appears on the last line.
Thanks.
It's because the initializer-string for your array of chars is too long
This
".fft"
is 5 characters long (including the NUL)
You've only allocated 4:
char fftc[4]; // .fft
If you really want those four characters and no NUL, try
struct ffthdr fhdr = {{'.','f','f','t'},1024,512,256,0,0,1};
I've never done any C++/COM work before, so I'm trying to hijack an existing solution and just alter it to my needs. The project was written and successfully compiled with VC 6 and I'm attempting to work with it now in 2010. I had to change a few references to get it to compile, but for some reason, the dll I generate is causing an exception on my system (the original works fine). Doing some research on the error, it looks like I'm getting a buffer overflow when I try to declare a char array.
bool CFile::simpleWrite(char* cData)
{
try{
// temp result variable
BOOL bResult = 0;
// file handle
HANDLE hFile = INVALID_HANDLE_VALUE;
// get the CMain singleton
CMain* m_pMain = CMain::GetInstance();
// this point gets synchronization to ensure we get unique file name...
char cDirFilename[MAX_PATH + 1];
GetLogFileName(cDirFilename, MAX_PATH);
// sanity check
if(strcmp(cDirFilename, "c:\\") == 0) assert(0);
// try and create a file
hFile = CreateFile( cDirFilename, GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
// if have a good file handle
if(hFile != INVALID_HANDLE_VALUE){
size_t lenFileData = strlen(cData) + 72;
char* cFileData = new char[lenFileData];
_snprintf(cFileData, lenFileData, "<?xml version=\"1.0\"?>\r\n<RootElement>\r\n%s</RootElement>\r\n\0", cData);
...
Here is the declaration/assignment for cData (cXML in the calling method).
char cXML[EVENT_LOG_MAX_MESSAGE];
// get the CMain singleton
CMain* pMain = CMain::GetInstance();
long lThreadID = GetCurrentThreadId();
// put the parameters into XML format
pMain->BuildXML(cXML, EVENT_LOG_MAX_MESSAGE,errLogLevel,userActivityID,methodName,lineNumber,className,AppID,errorDescription,errorID,lThreadID);
// write the data to file
if(!simpleWrite(cXML))
...
BuildXML is doing a _snprintf into cXML and returning it.
Here is the stacktrace going from my call into some of the VC files.
Test.dll!_heap_alloc_base(unsigned int size) Line 55 C
Test.dll!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 431 + 0x9 bytes C++
Test.dll!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 239 + 0x19 bytes C++
Test.dll!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302 + 0x1d bytes C++
Test.dll!malloc(unsigned int nSize) Line 56 + 0x15 bytes C++
Test.dll!operator new(unsigned int size) Line 59 + 0x9 bytes C++
Test.dll!operator new[](unsigned int count) Line 6 + 0x9 bytes C++
Test.dll!CFile::simpleWrite(char * cData) Line 87 + 0xc bytes C++
I'm sure there is some stupid basic mistake, but I can't seem to get it figured out.
Your error is most likely somewhere else where you end up corrupting the heap. I notice you use strlen here without adding one for the terminating zero. Have a look in your code to see if you use strlen for allocating memory and copying somewhere, because I think you're corrupting the heap by allocating one byte too little and then strcpy'ing to it.
As I suspected, this was all my own stupidity. This COM application had a dependency that I wasn't aware of. Never saw anything trying to look for it in the process monitor and the project had a local copy of the file for compile purposes apparently. Thanks for the input though.
I'm wondering if there really is no 128-bit division intrinsic function in Visual C++?
There is a 64x64=128 bit multiplication intrinsic function called _umul128(), which nicely matches the MUL x64 assembler instruction.
Naturally, I assumed there would be a 128/64=64 bit division intrinsic as well (modelling the DIV instruction), but to my amazement neither Visual C++ nor Intel C++ seem to have it, at least it's not listed in intrin.h.
Can someone confirm that? I tried grep'ing for the function names in the compiler executable files, but couldn't find _umul128 in the first place, so I guess I looked in the wrong spot.
Update: at least I have now found the pattern umul128 (without the leading underscore) in c1.dll of Visual C++ 2010. All the other intrinsics are listed around it, but unfortunately no "udiv128" or the like :( So it seems they really have "forgotten" to implement it.
To clarify: I'm not only looking for a 128-bit data type, but a way to divide a 128-bit scalar int by a 64-bit int in C++. Either an intrinsic function or native 128-bit integer support would solve my problem.
Edit: The answer is no, there is no _udiv128 intrinsic in Visual Studio 2010 up to 2017, but it is available in Visual Studio 2019 RTM
If you don't mind little hacks, this may help (64-bit mode only, not tested):
#include <windows.h>
#include <stdio.h>
unsigned char udiv128Data[] =
{
0x48, 0x89, 0xD0, // mov rax,rdx
0x48, 0x89, 0xCA, // mov rdx,rcx
0x49, 0xF7, 0xF0, // div r8
0x49, 0x89, 0x11, // mov [r9],rdx
0xC3 // ret
};
unsigned char sdiv128Data[] =
{
0x48, 0x89, 0xD0, // mov rax,rdx
0x48, 0x89, 0xCA, // mov rdx,rcx
0x49, 0xF7, 0xF8, // idiv r8
0x49, 0x89, 0x11, // mov [r9],rdx
0xC3 // ret
};
unsigned __int64 (__fastcall *udiv128)(unsigned __int64 numhi,
unsigned __int64 numlo,
unsigned __int64 den,
unsigned __int64* rem) =
(unsigned __int64 (__fastcall *)(unsigned __int64,
unsigned __int64,
unsigned __int64,
unsigned __int64*))udiv128Data;
__int64 (__fastcall *sdiv128)(__int64 numhi,
__int64 numlo,
__int64 den,
__int64* rem) =
(__int64 (__fastcall *)(__int64,
__int64,
__int64,
__int64*))sdiv128Data;
int main(void)
{
DWORD dummy;
unsigned __int64 ur;
__int64 sr;
VirtualProtect(udiv128Data, sizeof(udiv128Data), PAGE_EXECUTE_READWRITE, &dummy);
VirtualProtect(sdiv128Data, sizeof(sdiv128Data), PAGE_EXECUTE_READWRITE, &dummy);
printf("0x00000123456789ABCDEF000000000000 / 0x0001000000000000 = 0x%llX\n",
udiv128(0x00000123456789AB, 0xCDEF000000000000, 0x0001000000000000, &ur));
printf("-6 / -2 = %lld\n",
sdiv128(-1, -6, -2, &sr));
return 0;
}
A small improvement - one less instruction
extern "C" digit64 udiv128(digit64 low, digit64 hi, digit64 divisor, digit64 *remainder);
; Arguments
; RCX Low Digit
; RDX High Digit
; R8 Divisor
; R9 *Remainder
; RAX Quotient upon return
.code
udiv128 proc
mov rax, rcx ; Put the low digit in place (hi is already there)
div r8 ; 128 bit divide rdx-rax/r8 = rdx remainder, rax quotient
mov [r9], rdx ; Save the reminder
ret ; Return the quotient
udiv128 endp
end
It's available now. You can use _div128 and _udiv128
The _div128 intrinsic divides a 128-bit integer by a 64-bit integer. The return value holds the quotient, and the intrinsic returns the remainder through a pointer parameter. _div128 is Microsoft specific.
Last year it was said to be available from "Dev16" but I'm not sure which version is that. I guess it's VS 16.0 A.K.A VS2019, but the documentation on MSDN shows that it goes further to VS2015
I am no expert, but I dug this up:
http://research.swtch.com/2008/01/division-via-multiplication.html
Interesting stuff. Hope it helps.
EDIT: This is insightful too: http://www.gamedev.net/topic/508197-x64-div-intrinsic/
Thanks #alexey-frunze, it worked with little tweak for VS2017, checked with same parameters with VS2019:
#include <iostream>
#include <string.h>
#include <math.h>
#include <immintrin.h>
#define no_init_all
#include <windows.h>
unsigned char udiv128Data[] =
{
0x48, 0x89, 0xD0, // mov rax,rdx
0x48, 0x89, 0xCA, // mov rdx,rcx
0x49, 0xF7, 0xF0, // div r8
0x49, 0x89, 0x11, // mov [r9],rdx
0xC3 // ret
};
unsigned char sdiv128Data[] =
{
0x48, 0x89, 0xD0, // mov rax,rdx
0x48, 0x89, 0xCA, // mov rdx,rcx
0x49, 0xF7, 0xF8, // idiv r8
0x49, 0x89, 0x11, // mov [r9],rdx
0xC3 // ret
};
unsigned __int64(__fastcall* udiv128)(
unsigned __int64 numhi,
unsigned __int64 numlo,
unsigned __int64 den,
unsigned __int64* rem) =
(unsigned __int64(__fastcall*)(
unsigned __int64,
unsigned __int64,
unsigned __int64,
unsigned __int64*))
((unsigned __int64*)udiv128Data);
__int64(__fastcall *sdiv128)(
__int64 numhi,
__int64 numlo,
__int64 den,
__int64* rem) =
(__int64(__fastcall *)(
__int64,
__int64,
__int64,
__int64*))
((__int64*)sdiv128Data);
void test1()
{
unsigned __int64 a = 0x3c95ba9e6a637e7;
unsigned __int64 b = 0x37e739d13a6d036;
unsigned __int64 c = 0xa6d036507ecc7a7;
unsigned __int64 d = 0x7ecc37a70c26e68;
unsigned __int64 e = 0x6e68ac7e5f15726;
DWORD dummy;
VirtualProtect(udiv128Data, sizeof(udiv128Data), PAGE_EXECUTE_READWRITE, &dummy);
e = udiv128(a, b, c, &d);
printf("d = %llx, e = %llx\n", d, e); // d = 1ed37bdf861c50, e = 5cf9ffa49b0ec9aa
}
void test2()
{
__int64 a = 0x3c95ba9e6a637e7;
__int64 b = 0x37e739d13a6d036;
__int64 c = 0xa6d036507ecc7a7;
__int64 d = 0x7ecc37a70c26e68;
__int64 e = 0x6e68ac7e5f15726;
DWORD dummy;
VirtualProtect(sdiv128Data, sizeof(sdiv128Data), PAGE_EXECUTE_READWRITE, &dummy);
e = sdiv128(a, b, c, &d);
printf("d = %llx, e = %llx\n", d, e); // d = 1ed37bdf861c50, e = 5cf9ffa49b0ec9aa
}
int main()
{
test1();
test2();
return 0;
}