I am trying to port an unmanaged C++ Dll from one embedded device to another and am facing some strange problems which I think must have something to do with memorymanagement and/or compilers. I am not posting much code but describe what I tried as I have tried too many different things to post all code and I think the problem must be somewhere deeper within.
The first device is running WinCE 5.0 and is compiled using embedded Visual C++ 4.0.
The second device is running Windows Embedded Compact 7 (I will call it WinCE 7 for simplicity) and is compiled using VS2008. Both devices have their own SDKs designed for the boards.
On the first device the Dll is running without any problems, but on the second device the with ne new SDK compiled Dll is not working. Having a C# applikation on the second device I tryed PInvoke to access the dll but on the PInvoke line in Debug Mode got the error message:
Can't find PInvoke DLL NAME.dll
After some research I learnd this error can have differend causes:
Missing dependencies of the native library you are calling into.
The native assmebly was compiled for the wrong subsystem (i.e. desktop, not CE)
The native assembly was compiled for the wrong processor (i.e. x86 and not ARM)
Not enough virtual memory for the DLL to load.
I used peinfo to check the dll. All dependencies are being found on the device, it is compiled for WinCE 7 and the processor type is right. (I would have been surprised if not, using the right SDK) So there still is number 4: not enough virtual memory. But WinCE5 is limited to 32MB virtual memory and running while WinCE7 can have up to 2GB?
So I started to try some things to narrow the error in and will tell you my results.
First I took my dll compiled for the first device and tryed to use it on the second device. Surprisingly the .net application can find and PInvoke this one. But some functions inside the Dll don't seem to be running right so I guess I have to use the right SDK. But having the right code for both dll I know the exports must be right. I am aware the two compilers use different c++ name mangling styles so that is not the problem, too.
Next I wrote a simple c++ application on VS2008 using the new SDK to Load the Dll from there. On the first device the application runs this way but now on my remote Display on running on the second device I get the Error Message:
Unable to import library NAME.dll ! Program will exit.
At least now I know it has nothing to do with .net and PInvoke. But further on I made a simple new dll using VS2008 and the new SDK and ne .net application is able to PInvoke it. So there must be something in the code that doesn't like to be Loaded. :-/
After some hours of searching through the code I realised the system doesn't like some global variables. I know global variables are bad and I would be glad if they wouldn't be there, but I have not started the code and over the years they got more and more before me dealing with it, so they would be very hard to erase right now.
These globals are instances of classes. Some of them seem to be bad, some others seem to be ok. Confusingly they all are instances of classes and I don't know why there are good and bad ones. When I comment out the bad globals, the application is able to PInvoke the Dll. One of the bad globals is enough to make to applikation not find the Dll.
Why is it like this using VS2008 with WinCE 7 but not using eVC4.0 with WinCE 5? And what is the problem with the globals? How can I solve this problem? At best the same code should be working for both compilers but first I need some ideas, what is wrong with the second compiler.
I have found the solution to my Dll loading problem. The two systems have a different behaviour on #pragma pack. So eventually there was missalignment while loading the dll what made the dll crash. Because of the globals it was in the loading process of the dll, so the error message did not say something about missalignment but the standard "Can't find PInvoke DLL".
Related
I have developed a Delphi application (XE4) on a Windows XP machine.
When I copy all the project files to a Win 7 machine (also Delphi XE4) it will not compile.
The source has uses Vcl.Grids and the compiler complains it can't find vcl.grids.dcu.
Changing to uses grids works but I don't want to edit all the source.
I've checked the Embarcadero website for information on Namespaces but couldn't find anything useful.
I know it's possible to say uses vcl.grids under Win 7 so there must be some setting somewhere in the project that is preventing the resolution.
I've tried deleting the dproj files but that had no effect.
How do I get the source to compile with minimal changes?
The error has nothing to do with OS. It means your IDE/Projects's search paths are not configured correctly, or your project is missing references to the relevant packages, so double check that.
Also, you can use uses Grids in the code, and then make sure Vcl is listed in the Unit scope names field in the Project Options.
The information that you describe seems to be erroneous. The compiler is not affected by the operating system on which it runs. Running the same compiler on the same source code on a different operating system does not result in compiler errors.
Here are the reasonable explanations for your problem:
You are compiling the code on different versions of the compiler. Your error message matches what happens when you compile modern namespace aware code on XE or earlier.
Your are not compiling the same source code on both machines.
It is extremely hard to see beyond these two explanations.
Ok, red face time. Turns out I was running an earlier version of Delphi on the Win 7 machine. Delphi XE4 was installed along with an earlier version and I was invoking the earlier version.
Once I actually brought up XE4 on the Win 7 machine the issue vanished.
So I will don a hair shirt and crawl under my rock.
Thanks everyone who contributed.
In our program we are using a web service to pull back data from a third party into our program.
Ever since we updated to Delphi XE from Delphi 2009, Windows server 2003 users are receiving the following error message when making a SOAP call to the web service.
msvcrt.dll on Server 2003 does not have the procedure _ftol2_sse which is now being called for some reason..
I know this procedure was not being called when we had our source code on Delphi 2009 because I don't get this error on Windows server 2003 when running those builds.
Is this feasible? Could a change in the IDE affect which dll procedures are being called? Does anyone have any insight or ideas on how I might track down or fix this error?
Thanks
This is the third similar question you have asked on this topic. I'll attempt to give you some background information and help you work out what is going on.
First of all it's important to know that msvcrt.dll is a system component. It is not the MSVC runtime. It is supplied as part of Windows. Back in the bad old days, in the mid-90s, a lot of devlopers assumed that the MSVC6 runtime was always available. And they neglected to install that runtime as part of their program's installation. This occasionally caused trouble when the install program happened to find a machine without MSVC6.
The MSVC team moved to differently named runtime DLLs, msvcrt70.dll, msvcrt80.dll and so on. And they educated the developers that installing the MSVC runtime should be part of all MSVC application's installation programs.
But the Windows team wanted to help out legacy apps that had installers that assumed MSVC6 runtime was available. So they took the MSVC6 runtime under their control and started shipping it with Windows. I think this started around the time of Windows 2000 or XP.
The point I am trying to make is that msvcrt.dll is a system DLL over which you have no control. In your previous questions you have described your attempts to modify that DLL. Don't do that.
Now, from what I can glean, the version of msvcrt.dll that shipped with 2003 server does not export a function named _ftol2_sse. Hardly surprising since SSE floating point was not widely available back in the days of 2003 server. Clearly something in your system is resulting in an attempt to import _ftol2_sse.
You should be able to work out what is provoking this by using Dependency Walker. Use the functions on the Profile menu to start your application and study closely the logs. You should be able to see the chain of events that lead to an attempt to link to _ftol2_sse.
I'd be surprised if any of the Windows code linked to msvcrt.dll. That library is provided purely as a prop for legacy apps that link against MSVC6. But you never know.
Also try loading your executable in Dependency Walker. Look at the list of imported DLLs. Check to see if msvcrt.dll is in the list. If so, see what functions your executable imports, and if _ftol2_sse is in that list. If so then you'll be able to find it somewhere in the Delphi source code.
From the various similar sounding reports on the web I suspect that the problem you face is benign. Many of the people reporting the same issue can OK the dialogs and have their program continue without problem. This suggests that you can simply suppress the error reporting and so solve your problem. Use the SetErrorMode function to do so. You want to include the SEM_FAILCRITICALERRORS flag.
Be aware that SetErrorMode has a rather perverse interface. Almost all code that I have ever seen uses it incorrectly. Including the code in the Delphi RTL, and so many of the commonly used Delphi third party libraries. Raymond Chen, as usual, explains how to use it correctly.
Could switching compilers provoke the behaviour change? Certainly they could. Either the library code that you are using is implemented differently. Or perhaps the error mode is somehow different at the crucial moment.
I've been banging my head against this for the past two days and can't seem to make any progress...
Pretty much from one moment to the next, Delphi XE2 won't properly compile one of my projects any more. That is, it actually compiles without errors but at runtime I get resource not found errors for what is essentially the main "form" (it's actually a data module in this case). I have already reverted to older versions of the project from source control that I know were definitely working alright but to no avail. Judging by that it seems it must be something inside Delphi/the IDE itself rather than in the project source. However, I have also not been able to reproduce the issue with a simple test project nor with any other real-life projects... It only happens with this one.
Another strange thing is that when I look at the produced binary with XN Resource Explorer everything looks as it should: The form resource mentioned in the error message is actually there and intact...
At some point I was suspecting this might be caused by a bug in one of the experts I have installed in my IDE (e.g. Uwe's platform and OI experts and VersionInsightPlus, Andreas' IDEFixPack and DDevExtensions, GExperts) but even after disabling all these the problem persisted.
Unfortunately, I am unable to track down exactly when this started to happen as I had been working for some time without actually running the binary, fixing compiler warnings and errors for the x64-target, adjusting build events for updated third-party tools (localization and license protection) and such things...
Has anyone else ever seen anything like this happen? Any more ideas on how to pin this down?
Some more details about the project:
It is an addin for Outlook built using the Add-In-Express framework (i.e. a COM-DLL).
The "main form" is a TDataModule-descendant - we also inserted our own ancestor-class into the hierarchy, i.e. the "addin module" is not directly inheriting from TadxCOMAddInModule - the resources of the custom ancestor forms also appear to be present and intact in the output binary when checking with a resource viewer.
Built without runtime packages for the Win32 and Win64 platforms.
Let me know if you think I missed to mention any other potentially relevant details.
Update:
I have now transferred the sources in question onto a different machine. Interestingly, the DLL I compiled there did not exhibit the problem - on that machine that is... when I transfered it back to the original machine and I tried to call it, the error was back (to stress this: this was the exact same DLL producing a EResNotFound on one machine but not on the other. Of course, once I had discovered this, I also performed the reverse test and lo and behold, the DLL compiled on the original machine works without errors on the other machine...
Seems this might not be a Delphi problem after all... but what is it then?
Differences between the two machines:
Machine 1 (the one were the problem occurs): Windows 7 Ultimate English 64bit with Delphi XE2 Update 4
Machine 2: Windows 7 Professional German 32bit with Delphi XE2 Update 3
On a third machine that is almost identical to the first except that it doesn't have Delphi on it, DLLs produced by both machines work flawlessly.
I am a bit surprised to see your question here. :)
We faced a number of serious issues with recent Update 4 for Delphi XE2. Though we have never run into or been reported of the "resource not found" error, I think this update might be one of the causes. Have you installed it?
One more thing that comes to my mind is images that you use for your Office controls (command bar and ribbon). Probably they got broken somehow, the run-time code cannot load them and reports this error.
Anyway, as you understand, these are just my guesses, if you need our assistance with your office add-in please contact Add-in Express support service, we will try to help.
Update: Seems I was a bit too quick, drawing conclusions. Apparently the Sisulizer solution is also supposed to perform a fallback to the main resource block. I have now taken this issue to the product forum and will report back here, once this is resolved.
Alright, mystery solved at last:
I had turned off the option to "Copy all resources" in Sisulizer in an attempt to reduce the size of the produced resource DLLs and then had forgotten about it...
I hadn't fully realized the implications of the standard Delphi resource DLL approach to localization on which Sisulizer "piggybacks" - especially that it was an all-or-nothing deal: Our previous translation solution implemented a fallback-mechanism that would read any resources not found in the external resource DLL from the host binary instead. This does not appear to be the case with Sisulizer - at least not out of the box... thus, any resource that's not contained in the localized resource DLL does not exist as far as the application is concerned.
I also didn't realize that the mere existence of a file with the same base name as the main binary and an extension matching the current system's default locale (such as .EN or .DE) would automatically cause the VCL to load it...
The machines that did not exhibit the error either still had the older, larger (=complete) resource DLLs on them, or no resource DLLs at all.
We are trying to split up our monolithic EXE into a combination of an EXE and several packages. So far, we have one package that we're trying to use, and when running the EXE Codeguard shows the following error on startup:
CG Error
Two different CRTLDLLs are loaded. CG might report false errors
(C:\Windows\system32\CC32100MT.DLL)
(D:\Projects\Foo\Bar.bpl)
OK
I read this as two different runtime libraries being loaded - one, the correct one (CC32100MT.dll), one incorrect, which is the package we're trying to use.
Continuing to run the program shows odd errors, especially casting between classes or passing a pointer to a class as a parameter in a method that crosses the EXE/DLL boundary. Codeguard itself doesn't show any other errors at all though. Edit: This is now resolved, and wasn't related. The program appears to run correctly, but the warning Codeguard shows is still worrying.
How do we solve this?
Some more details
We've looked at as many things as we (the developer working on this and I) can collectively think of:
Each project is built using runtime packages. The EXE host lists Bar in its package list.
Each project is set to compile with dynamic RTL. However, changing this does not solve the problem.
The package is linked to the EXE via its BPI file, but linking via a LIB makes no difference either.
The EXE and BPL are compiled with the same project settings, where the same options exist for both types of project. We think, anyway :)
There is only one copy of the BPL and BPI on the system: it's definitely linking to the right one.
Examining the EXE and BPL with Depends and TDump show they are both using C:\Windows\system32\CC32100MT.DLL. They should both be using the one RTL.
Creating a new project (a plain VCL forms application) and linking to the BPL (via its BPI) works fine. Something in the process of adding all the files and LIBs that make our EXE contain the code it needs to changes this, but we haven't been able to figure out what.
The LIBs all either correspond to DLLs we use (flat C interface, usually look as though they were built with MSVC) or are simple projects with lots of related files, compiled to a lib for the purpose of linking into the EXE - these correspond roughly to the areas of the program we want to split to BPLs, by the way. There don't seem to be project options for the LIB projects that would affect RTL linking, unless we've missed them.
I have exhaustively hunted through Depends and looked at all RTL and CC32*.dll files the EXE and every single DLL references. All are identical: rtl140.bpl and CC32100MT.DLL. Fully qualified paths show they are the same files, too. Everything should be using the one same run-time library.
Edit: The final EXE is complex, built with several libs, several DLLs, etc. All these, when built with C++Builder, are built with the current version. Is it possible there's something in one of these DLLs or LIBs that could cause a problem? I don't know enough about how the RTL is linked in to be sure about where to look... my (naive?) assumption is that the linker would normally link in one set of RTL functions, but that of course doesn't seem to be happening... and I don't know how things change when using packages. Is it possible this error has always existed and Codeguard has not flagged it before, because we haven't used something dynamic like a package?
Perhaps another question is, Why would a package have its own RTL anyway, or what would make it count as 'a RTL DLL' to Codeguard?
We're stumped. Absolutely stumped. We've had other problems using BPLs (they seem to be surprisingly tricky things, especially using C++) but have managed to solve them all. This one we've had no luck at all and we'd really appreciate any insights :)
We're using C++Builder 2010 (as part of RAD Studio actually, but with little Delphi code apart from components.)
Edit: Started a bounty. I'd really like to solve this!
Edit 2: Thanks to David Dean for his help (marked as answered below.) Via email, he pointed out this issue was reproduced in a simple test case by someone else, and is logged in Embarcadero QC as report 86335. Currently there is no fix, but the warning does not appear to indicate a genuine problem (ie, it's probably a spurious error, and while it's a pity to have to click past the dialog when you run, hopefully there's nothing in the error to worry about.)
Since one of these is coming from a .bpl, did you try turning off "Build with runtime packages" in the project options?
We had a similar problem. We tracked it down to a (non VCL) .cbproj that was created without the "Multithreaded" option.
As far as I can tell, the only time you get chance to set this option is when you create a new .cbproj, it cannot be changed afterwards using the GUI. We ended up "hacking" the .cbproj to include the following:
<Multithreaded>true</Multithreaded>
To determine which dll is causing the issue, it should be the last dll loaded in the output window just before you see the CG message.
Did you check if you use _TCHAR as char. We had some similar problems with RAD Studio and we found a workaround using _TCHAR as char. As soon as one DLL or BPL Project is compiled with wchar_t, this code guard error appears.
We also figured out, that EXE projects can be compiled with TCHAR = wchar_t without any problem (the main function will be WIDE).
The settings does not affect the GUI being able to handle UNICODE.
A customer logged a similar case in our public bug tracking system and the bug has been identified and fixed in the latest release.
HI:
I've a Delphi 7 program that I wrote many years ago, but I've lost the source code. It's a small program but very useful for me.
I've tried to 'install' it again in a new Windows XP computer, just copying the folder with de data (.db paradox files), and configured the BDE connection.
When the programm starts I receive an "Unknown exception" and halts. I've no idea why this happens, and can't debug cause the lost source code. I've tried in another computer with the same results.
Any suggestions or ideas? What do you do in a situation like this?
Thanks in advance.
EDIT:
When I installed Delphi 7 in the new XP computer, the exception came from unknown to known. It was something related to the folder for the Paradox.net file. Thnk you all.
Delphi IDE can attach to a running process and debug it (Run -> Attach to process), although without debug symbols you will end up debugging plain assembler code, which requires some knowledge of assembler and how a Windows application works. And debugging startup exceptions could be pretty difficult if the debugger can't start the program. You can also use the WinDbg debugger from Microsoft.
There are disassemblers (I used the very powerful IDA Pro) that are able to recognize standard library calls helping analysys a lot. You may also find decompilers, although decompiling native applications is a bit more difficult than with those using a p-code or the like.
If the error is not due to a misconfiguration, patching a binary file is not easy.
You can use any debugger, either Visual Studio one, or a free OllyDbg, don't know if Delphi IDE have a simple external-exe-debugger.
But debugging will be very hard w/o source codes, and you must have at least basic knowledge of Assembler Language and win32api.
Alternatively you can use tools like FileMon & RegMon to examine your app activity and find potential problems.
You can try "Run|Connect to process..." in the Delphi IDE. But what zed_0xff said regarding debbugging without sources still applies.
I would go for the disassemble approach like ldsandon suggest, especially since you have (some) knowledge about what your exe is doing.
Besides IDA Pro also take a look at tools aimed specifically at Delphi such as IDR (Interactive Delphi Reconstructor), DeDe and PE Explorer.
To make sure it is not BDE related, I would build another rudimentary application trying to access the same data on this machine.
Once this application works, you can move on to test on the Pascal code side of things.
I have had my share of BDE oddities so I'd prefer to rule this out.