I've been coding a game for the past year, I'm in the process of porting to Mac.
I've set everything up according to: http://blog.davidecoppola.com/2013/08/22/how-to-set-up-a-sdl-2-project-for-os-x-in-xcode-4/. I have changed some of the steps to compensate for the version (5).
In my code I use tinyXML to load a .xml file within an assets folder. This works perfectly on windows and linux, however, in Mac I experience some issues. Here's the line:
Doc.LoadFile(DataPath);
Doc is a tinyxml2::XMLDocument type, and the DataPath is usually "assets/Data.xml", in Mac I hard-coded that line into the place of "DataPath".
When running the code within the IDE I experience no issues and my game comes up and plays like it does on all other platforms, however, when running the .app file (Located in gameMac/Build/Products/Debug) it crashes right after starting up. The Assets folder is also located in this location.
Here's the error Mac throws at me after the crash:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 gameMac 0x000c1525 tinyxml2::XMLNode::FirstChildElement(char const*) const + 21
1 gameMac 0x000d1954 tinyxml2::XMLNode::FirstChildElement(char const*) + 36
2 gameMac 0x000d04d5 DataLoader::load(char const*, ID_Data, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) + 197
3 gameMac 0x000a5849 MapHandler::MapHandler(std::__1::shared_ptr<gameData>) + 1177
4 gameMac 0x000a539e MapHandler::MapHandler(std::__1::shared_ptr<gameData>) + 30
5 gameMac 0x000b7eb8 splay::splay(std::__1::shared_ptr<gameData>) + 1592
6 gameMac 0x000b786e splay::splay(std::__1::shared_ptr<gameData>) + 30
7 gameMac 0x000ee3f9 std::__1::shared_ptr<splay> std::__1::shared_ptr<splay>::make_shared<std::__1::shared_ptr<gameData>&>(std::__1::shared_ptr<gameData>&&&) + 1849
8 gameMac 0x000ebc7c stateHandlerGen::stateHandlerGen(std::__1::shared_ptr<gameData>) + 236
9 gameMac 0x000ebb7e stateHandlerGen::stateHandlerGen(std::__1::shared_ptr<gameData>) + 30
10 gameMac 0x000e7a89 game::init(char const*, int, int, int, int, bool) + 1545
11 gameMac 0x000be8c4 main + 516
12 libdyld.dylib 0x91b3c725 start + 1
(Please note that gameMac is not the name of my project, I have changed that detail due to an NDA).
As I've noted here, the same method that loads my data DataLoader::load(params) is giving the crash. This leads me to believe that my assets folder is not being loaded into my .app file.
Through this I attempted to edit a Build Phase, Copy Bundle Resources this did not change the issue. I then attempted to make a New Build Phase Copy Files and set it to Resources, this also failed. I then experimented by setting the Copy Files to Product Directory; this copied the assets folder to the build folder, but the .app file still won't load in the assets.
Did I miss something? Could some XCode vets help me out here, I've attempted to fix this for the past few days. Thanks.
http://pastebin.com/Xq4Hxh4d (Here's the top of my DataLoader as mentioned above. EDIT: Added in my check for nullptr return, yes, it returns true if failed).
P.S I can only give out snippets of my code, I have given what I feel is most likely the problem, resource loading :)
The full crash report is in the comments below.
The fix, thanks to the help from Brad Allred:
The resources are located within the .app file, specifically {Application}/Contents/Resources ; in my case I wanted to access a file within assets. I did a build phase to copy the data to the resources folder, making my directory {Application}/Contents/Resources/Assets/../. Using SDL_GetBasePath I'm able to create a string which is the absolute path from your base directory up to the Resources folder.
Here's the code:
if(Doc.LoadFile("assets/Data.xml"))
{
std::string path = (std::string)SDL_GetBasePath() + "assets/Data.xml";
if(Doc.LoadFile(path.c_str()))
{
return false;
}
}
I concat the base path + whatever data I need, and pass the .c_str() version to tinyXML. If I find a better/cleaner version I'll be sure to update it here.
your crash report tells you the line number in your code that is crashing (tinyxml2.cpp:745). at Probably your assets are not where the app expects them to be or doesnt have permission. examining your DataPath to see where its trying to load should get you started.
It seems like maybe you are mistakenly assuming that you can use a relative path and get assets relative to the app bundle; you can't do that.
Since you are using SDL, why not use the SDL API (see SDL_GetBasePath) to get resource paths so that you can store your assets properly inside your app bundle in the Resources directory?
Related
This might be a general question, but this problem is really getting me confused.
I have two different C++ applications, compiled with Visual Studio 2012, needing an instance of the same object. I have put a breakpoint before the creation of each object to measure the RAM usage by stepping my programs. The first one takes approximately 2.5 MiB more RAM after creating the object, while the second app is taking 30 MiB!
Both objects are created using a simple call to new with the same parameters. The code behind the constructors is the same.
As a detail: the first project contains much fewer .cpp files than the second one. So I thought it might be a problem of internal fragmentation of the exe. Plus, I've also tried to break BEFORE any code was executed inside the main function, and the memory usage was already much different (6 MiB for the first app, 35 MiB for the second one).
Does anyone have any idea what might be going on?
EDIT : The said object is a DirectX context, with a constructor creating a Direct3D instance and a device. Both the instance AND device are created the same way, but both have different RAM usage between the two apps.
Here is the code for the D3D device creation :
d3d_presentParams = new D3DPRESENT_PARAMETERS; ZeroMemory( d3d_presentParams, sizeof(D3DPRESENT_PARAMETERS) );
d3d_presentParams->Windowed = !window->isFullscreen();
d3d_presentParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
d3d_presentParams->hDeviceWindow = window->getHwnd();
d3d_presentParams->MultiSampleType = antiAlias;
d3d_presentParams->EnableAutoDepthStencil = true;
d3d_presentParams->AutoDepthStencilFormat = D3DFMT_D32F_LOCKABLE;
d3d_presentParams->PresentationInterval = (info.m_vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
{
d3d_presentParams->BackBufferCount = 1;
d3d_presentParams->BackBufferFormat = D3DFMT_A8R8G8B8;
d3d_presentParams->BackBufferWidth = m_viewportSize.x;
d3d_presentParams->BackBufferHeight = m_viewportSize.y;
}
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
window->getHwnd(),
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
d3d_presentParams,
&d3d_device);
EDIT 2 : Problem has been "solved" for now. See the answer below.
Alright, I "solved" it, kind of. You're not going to believe what the problem was.
TL;DR : Renaming the executable lowers the RAM usage from 80 MiB to 28 MiB. It seems that Windows is suspicious of non-verified applications, as I discovered a directory full of logs inside C:/Users/<Me>/AppVerifierLogs/.
It seemed that RAM usage was linked to how many sources files it contained. Thus, I tried copying one of my projects entirely. I had to rename it, because a solution cannot have two projects with the same name... And guess what, memory usage was down to 7.3 MiB at the beginning of main(), instead of 30 MiB previously.
Later, I found out that it was a specific executable name that caused it to use more memory. I simply renamed the .exe file, and the problem was gone. I even tried to rename Firefox's exe by my app's name, and it made it crash.
And finally, I discovered in C:/Users/<me>/AppVerifierLogs/ at least 3000 files named after my application. This immediately made me think about the way Windows tries to verify applications (e.g. in order to see if they're not viruses).
I have no idea where this is coming from, nor how to turn off this verfier, but it's really annoying as a dev to have Windows panicking about an application you're developping, and injecting (possibly useless) stuff inside it.
The fix for now is just to rename the executable. If anyone knows about which application might have access to this "AppVerifierLogs" directory, please mention it, because even Google searches dont't seem to be able to help at this point...
I have an OCaml program that writes another OCaml program, compiles it and then tries to dynamically load it. Unfortunately this causes a segmentation fault on my OSX 10.14 machine, OCaml 4.07.1.
In particular my program is structured as follows:
File A statically loads a bunch of modules (call them Helper modules for reference), and defines: 1. a module signature that describes the module that will be dynamically loaded, 2. a reference of an option of this module, to be set by the loaded plugin 3. another module that uses this reference.
open Helper
module type PLUGIN_TYPE = sig ... end
let plugin = ref None
let get_plugin () : (module PLUGIN_TYPE) =
match !plugin with
| Some x -> x
| None -> failwith "No plugin loaded"
module Test
struct =
... get_plugin () ...
end
File B is the loader, in short it runs Dynlink.loadfile
File C is the generated OCaml file, which also uses the Helper modules and defines a module of type PLUGIN_TYPE and sets the plugin reference.
module Plugin : PLUGIN_TYPE =
...
end
let () = A.plugin := Some (module Plugin : PLUGIN_TYPE)
I use ocamlbuild to build the main program and then ocamlbuild again to build the plugin (which requires the same Helper modules/files as the main program).
When I try to run this I get a segfault, presumably around the time Dynlink.loadfile is executed. I am not sure what I am doing wrong, the fact that I am linking the Helper modules with both the main program and the plugin makes me uncomfortable but I am not sure how to work around it.
Attaching an LLDB trace:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x00000001002624da Main.native`caml_oldify_local_roots at roots.c:286 [opt]
frame #1: 0x00000001002664fb Main.native`caml_empty_minor_heap at minor_gc.c:352 [opt]
frame #2: 0x0000000100266cc5 Main.native`caml_gc_dispatch at minor_gc.c:446 [opt]
frame #3: 0x000000010026dca6 Main.native`caml_make_vect(len=<unavailable>, init=<unavailable>) at array.c:335 [opt]
frame #4: 0x0000000100114eb9 Main.native`camlLru_cache__init_inner_2624 + 89
frame #5: 0x0000000100087ea6 Main.native`camlSyntax__memoize_7621 + 38
frame #6: 0x000000010312d317 Plugin.cmxs`camlInterp__entry + 311
frame #7: 0x0000000100283424 Main.native`caml_start_program + 92
frame #8: 0x000000010027ad19 Main.native`caml_callback(closure=<unavailable>, arg=<unavailable>) at callback.c:173 [opt]
frame #9: 0x000000010027f6a0 Main.native`caml_natdynlink_run(handle_v=4345299456, symbol=72181230668639817) at natdynlink.c:141 [opt]
frame #10: 0x000000010009d727 Main.native`camlDynlink__fun_2440 + 23
frame #11: 0x0000000100183581 Main.native`camlStdlib__list__iter_1148 + 33
frame #12: 0x000000010009d5bc Main.native`camlDynlink__loadunits_2288 + 332
frame #13: 0x000000010009d788 Main.native`camlDynlink__load_2301 + 72
frame #14: 0x000000010000552c Main.native`camlLoader__load_plugin_1002 + 268
frame #15: 0x00000001000055d8 Main.native`camlLoader__simulate_1056 + 120
frame #16: 0x00000001000052c8 Main.native`camlMain__entry + 280
frame #17: 0x0000000100002489 Main.native`caml_program + 3481
frame #18: 0x0000000100283424 Main.native`caml_start_program + 92
frame #19: 0x00000001002617dc Main.native`caml_startup_common(argv=0x00007ffeefbff538, pooling=<unavailable>) at startup.c:157 [opt]
frame #20: 0x000000010026184b Main.native`caml_main [inlined] caml_startup_exn(argv=<unavailable>) at startup.c:162 [opt]
frame #21: 0x0000000100261844 Main.native`caml_main [inlined] caml_startup(argv=<unavailable>) at startup.c:167 [opt]
frame #22: 0x0000000100261844 Main.native`caml_main(argv=<unavailable>) at startup.c:174 [opt]
frame #23: 0x00000001002618bc Main.native`main(argc=<unavailable>, argv=<unavailable>) at main.c:44 [opt]
frame #24: 0x00007fff6d4f1ed9 libdyld.dylib`start + 1
frame #25: 0x00007fff6d4f1ed9 libdyld.dylib`start + 1
For what it's worth those are part of what I called Helper modules:
frame #4: 0x0000000100114eb9 Main.native`camlLru_cache__init_inner_2624 + 89
frame #5: 0x0000000100087ea6 Main.native`camlSyntax__memoize_7621 + 38
Any clues on what I am doing wrong?
TL;DR; Known bug. Use dune if possible. If not use Findlib Dynlink manually. Some work is needed but is doable. You're not the first one to hit this problem.
The Problem
First of all, you're doing everything right, it is a relatively well-known long-term bug in OCaml. Despite this, it was resolved only recently. Don't worry, there are a couple of workarounds (mentioned below). Besides, FYI, if you are not touching the Obj module or playing with external (C) stubs, and getting a segfault, then this is definitely a bug in the OCaml system, so you can go directly to the OCaml issue tracker. Fortunately, this happens very rarely.
Now, what is happening? The problem is that the OCaml dynamic linker is not checking whether a compilation unit is already loaded. Therefore, when you load a new unit, it could be already loaded or, in turn, load another unit which was already loaded. When a unit is loaded into OCaml process image the unit constructor (the initialization function) is called which sets the initial roots (global variables) and initializes the frames. If the unit was already initialized it breaks havoc - variables are reset, values are rewritten. If you're lucky, you will get a segmentation fault from the garbage collector. And this is what happens in your case.
Solutions
The fix was merged in the OCaml 4.08 version, but you probably won't be really happy with it. Yes, you won't get a segfault, but instead, your program will fail gracefully with an error indicating that you're trying to load a compilation unit which is already in the process image (the Dynlink.Error (Module_already_loaded "module name") exception). So it is the responsibility of a plugin system developer, to maintain the list of already loaded modules.
Most likely, you don't want to develop a new system. And the good news is that such systems were already developed (and they even work for old versions of OCaml, so they are robust to prevent OCaml from segfaulting).
I will provide two solutions below. Both are relying on Findlib Dynload facility. Which when a program (or shared object) is compiled records the list of compilation units that constitute it inside the program itself, so that later it could be consulted and a decision could be made, whether the unit should be loaded, and whether it is consistent with the units already loaded (e.g., we don't want to have multiple versions of the same library in the process image).
Dune
The solution number one would be to use Dune. Well, at least because it requires a minimum of work. Dune is implemented from scratch to work correctly with Findlib, so everything should work out of the box. You just need to port your project to Dune, specify findlib.dynload as the dependency of your host program (the program that loads the plugins) and use the Fl_dynload.load_packages to load your plugins.
OCamlbuild/OASIS
If you can't for some reasons move your project to Dune, then you have to do some work yourself. We have implemented our own plugin loading system as a part of the BAP project, so you can build your own system based on it. It is under the MIT license, so feel free to grab any code you like and modify it to your taste. Our system is providing a little bit more than you might need (we make our plugins self-contained, pack them as zip files, etc), but the idea is the same - use Fl_dynload and keep track on what you're loading. As always, the devil is in the details. If you're using OASIS or ocamlbuild to build non-trivial project (and if your project is trivial, then just port it to Dune), then the caveat is that when ocamlbuild links an internal libraru (i.e., a library from your source tree) it won't use OCamlFind and therefore the linked modules wouldn't be reported to the Dynload facility. Therefore we have to write an OCamlBuild plugin which will do this.
Basically, your loader must track which compilation units are already loaded, and your plugin must contain meta information that tells the loader which compilation units it requires and which it provides. This requires quite a cooperation from all the parts. Here is how it works in BAP:
1) We have the bapbuild tool which is the ocamlbuild enhanced with an (ocamlbuild) plugin that knows how to build *.plugin files. A .plugin file is a zip file underneath the hood with a fixed layout (called bundle in our parlance). It contains a MANIFEST file which includes the list of required libraries and a list of provided units, along with some meta information and, of course, the cmxs (and cma) for the code itself. Optionally, the bundle may include all the dependent libraries (to make the plugin loadable in environments where the required libraries are not provided). The bapbuild tool will package all the dependencies by default, and since some libraries in the OPAM universe do not provide cmxs at all it will also build cmxs for them and package them into the plugin. Note,
2) We have the bap_plugins runtime library which loads plugins, fulfilling their dependencies and ensuring that no units are loaded twice.
3) Since the host program (which loads plugins) may (and will) also contain some compilation units in it, as it will be linked from some set of compilation units that are either local to the project tree or come from external libraries. So we need some cooperation from the build system that shall tell us which units are already loaded (alternatively we can parse the ELF structures of the host binary, but this doesn't sound as a very portable and robust solution). We use ocamlfind.dynlink library which enables such cooperation, by storing a list of libraries and packages that were used to build a binary in an internal data structure. We wrote a small pocamlbuild plugin]6 that enables this and the rest is done by ocamlfind (which actually generates a file and links it into the host binary).

I'm not sure if this is the cause of your segfault, but your line:
let A.plugin = Some (module Plugin : PLUGIN_TYPE)
is wrong. What you want to write is:
let () = A.plugin := Some (module Plugin : PLUGIN_TYPE)
Ideally, I would advise you to create a function register_plugin in A to avoid this kind of mistake.
Also, you'd probably want to know if the build of your plugin fails and handle that properly.
The go test command has support for the -c flag, described as follows:
-c Compile the test binary to pkg.test but do not run it.
(Where pkg is the last element of the package's import path.)
As far as I understand, generating a binary like this is the way to run it interactively using GDB. However, since the test binary is created by combining the source and test files temporarily in some /tmp/ directory, this is what happens when I run list in gdb:
Loading Go Runtime support.
(gdb) list
42 github.com/<username>/<project>/_test/_testmain.go: No such file or directory.
This means I cannot happily inspect the Go source code in GDB like I'm used to. I know it is possible to force the temporary directory to stay by passing the -work flag to the go test command, but then it is still a huge hassle since the binary is not created in that directory and such. I was wondering if anyone found a clean solution to this problem.
Go 1.5 has been released, and there is still no officially sanctioned Go debugger. I haven't had much success using GDB for effectively debugging Go programs or test binaries. However, I have had success using Delve, a non-official debugger that is still undergoing development: https://github.com/derekparker/delve
To run your test code in the debugger, simply install delve:
go get -u github.com/derekparker/delve/cmd/dlv
... and then start the tests in the debugger from within your workspace:
dlv test
From the debugger prompt, you can single-step, set breakpoints, etc.
Give it a whirl!
Unfortunately, this appears to be a known issue that's not going to be fixed. See this discussion:
https://groups.google.com/forum/#!topic/golang-nuts/nIA09gp3eNU
I've seen two solutions to this problem.
1) create a .gdbinit file with a set substitute-path command to
redirect gdb to the actual location of the source. This file could be
generated by the go tool but you'd risk overwriting someone's custom
.gdbinit file and would tie the go tool to gdb which seems like a bad
idea.
2) Replace the source file paths in the executable (which are pointing
to /tmp/...) with the location they reside on disk. This is
straightforward if the real path is shorter then the /tmp/... path.
This would likely require additional support from the compiler /
linker to make this solution more generic.
It spawned this issue on the Go Google Code issue tracker, to which the decision ended up being:
https://code.google.com/p/go/issues/detail?id=2881
This is annoying, but it is the least of many annoying possibilities.
As a rule, the go tool should not be scribbling in the source
directories, which might not even be writable, and it shouldn't be
leaving files elsewhere after it exits. There is next to nothing
interesting in _testmain.go. People testing with gdb can break on
testing.Main instead.
Russ
Status: Unfortunate
So, in short, it sucks, and while you can work around it and GDB a test executable, the development team is unlikely to make it as easy as it could be for you.
I'm still new to the golang game but for what it's worth basic debugging seems to work.
The list command you're trying to work can be used so long as you're already at a breakpoint somewhere in your code. For example:
(gdb) b aws.go:54
Breakpoint 1 at 0x61841: file /Users/mat/gocode/src/github.com/stellar/deliverator/aws/aws.go, line 54.
(gdb) r
Starting program: /Users/mat/gocode/src/github.com/stellar/deliverator/aws/aws.test
[snip: some arnings about BinaryCache]
Breakpoint 1, github.com/stellar/deliverator/aws.imageIsNewer (latest=0xc2081fe2d0, ami=0xc2081fe3c0, ~r2=false)
at /Users/mat/gocode/src/github.com/stellar/deliverator/aws/aws.go:54
54 layout := "2006-01-02T15:04:05.000Z"
(gdb) list
49 func imageIsNewer(latest *ec2.Image, ami *ec2.Image) bool {
50 if latest == nil {
51 return true
52 }
53
54 layout := "2006-01-02T15:04:05.000Z"
55
56 amiCreationTime, amiErr := time.Parse(layout, *ami.CreationDate)
57 if amiErr != nil {
58 panic(amiErr)
This is just after running the following in the aws subdir of my project:
go test -c
gdb aws.test
As an additional caveat, it does seem very selective about where breakpoints can be placed. Seems like it has to be an expression but that conclusion is only via experimentation.
If you're willing to use tools besides GDB, check out godebug. To use it, first install with:
go get github.com/mailgun/godebug
Next, insert a breakpoint somewhere by adding the following statement to your code:
_ = "breakpoint"
Now run your tests with the godebug test command.
godebug test
It supports many of the parameters from the go test command.
-test.bench string
regular expression per path component to select benchmarks to run
-test.benchmem
print memory allocations for benchmarks
-test.benchtime duration
approximate run time for each benchmark (default 1s)
-test.blockprofile string
write a goroutine blocking profile to the named file after execution
-test.blockprofilerate int
if >= 0, calls runtime.SetBlockProfileRate() (default 1)
-test.count n
run tests and benchmarks n times (default 1)
-test.coverprofile string
write a coverage profile to the named file after execution
-test.cpu string
comma-separated list of number of CPUs to use for each test
-test.cpuprofile string
write a cpu profile to the named file during execution
-test.memprofile string
write a memory profile to the named file after execution
-test.memprofilerate int
if >=0, sets runtime.MemProfileRate
-test.outputdir string
directory in which to write profiles
-test.parallel int
maximum test parallelism (default 4)
-test.run string
regular expression to select tests and examples to run
-test.short
run smaller test suite to save time
-test.timeout duration
if positive, sets an aggregate time limit for all tests
-test.trace string
write an execution trace to the named file after execution
-test.v
verbose: print additional output
A model glue site we use had to be moved to another physically different location. I updated all the paths in ModelGlue.xml, ColdSpring.xml and other specific files, but I keep getting the following error. Note: the current physical path is jmc.divisions.medical_oncology.admin.controller.Controller
Could not find the ColdFusion Component or Interface jmc.medical_oncology.admin.controller.Controller.
Ensure that the name is correct and that the component or interface exists.
The error occurred in E:\Inetpub\framework\ModelGlue\unity\loader\XmlConfigurationLoader.cfc: line 234
Called from E:\Inetpub\framework\ModelGlue\unity\loader\XmlConfigurationLoader.cfc: line 83
Called from E:\Inetpub\framework\ModelGlue\unity\loader\FrameworkLoader.cfc: line 98
Called from E:\Inetpub\framework\ModelGlue\unity\ModelGlue.cfm: line 116
Nevermind! Apparently, the system held onto some app-level caching for almost 48 hours. It finally works now.
I am currently trying to get to the bottom of a client crash with one of our applications. I have wrapped the app in an exception handler which creates a mini-dump when the crash occurs.
The application crashes with the exception c0000139 (of which there isn't a huge amount of documentation).
The callstack looks like this
ntdll.dll!_RtlRaiseStatus#4() + 0x26 bytes
ntdll.dll!_LdrpSnapThunk#32() + 0x26f48 bytes
ntdll.dll!_LdrpSnapIAT#16() + 0xd9 bytes
ntdll.dll!_LdrpHandleOneOldFormatImportDescriptor#16() + 0x7a bytes
ntdll.dll!_LdrpHandleOldFormatImportDescriptors#16() + 0x2e bytes
ntdll.dll!_LdrpWalkImportDescriptor#8() + 0x11d bytes
ntdll.dll!_LdrpLoadDll#24() - 0x265 bytes
ntdll.dll!_LdrLoadDll#16() + 0x110 bytes
kernel32.dll!_LoadLibraryExW#12() + 0xc8 bytes
odbc32.dll!_ODBCLoadLibraryEx#12() + 0x29 bytes
odbc32.dll!_LoadDriver#12() + 0x119f bytes
odbc32.dll!_SQLDriverConnectW#32() + 0x1be bytes
odbc32.dll!_SQLDriverConnect#32() + 0x125 bytes
It looks like the program is trying to create a database connection (to Oracle via ODBC) and somehow failing to either find the dll or has found a dll with the wrong entry point.
I was wondering if anyone could offer advice an how to track this problem down further, or if anyone has experienced this problem I'd be interested in hearing how you solved it.
Thanks in advance
Rich
That exception code is Entry point not found - something is trying to load a DLL and the DLL cannot find all the DLLs it needs.
Use depends.exe to show what the DLL requires.
Enable loader snaps (gflags -i yourapp.exe +sls) and have it pinpoint the library its failing to find/load (starting the program under the debugger will spew all the loader diagnostics).
Alternatively, get the name of the library from the crash dump by examining parameters of LoadLibraryExW call.
Thanks for all the responses.
Turns out (at least this seems like it was the problem) that we had a configuration problem. Half of the software was set to load the 9i drivers and half of the software was expecting the 10g drivers.
It's early days yet and we need to test this, however it seems very likely that this was the cause.
Cheers
Rich