Search code examples
c++cvisual-studiovisual-studio-2019visual-studio-6

How do I compile a C project in Visual Studio 6 without it needing LIBCD.lib?


I've compiled VolPack (https://graphics.stanford.edu/software/volpack/) as a static library in Visual Studio 6 (under Windows XP) because I think that's what it was made for and it wouldn't compile under Visual Studio 2019. But trying to write a C++ program in Visual Studio 2019 and link to volpack.lib I get the error: Error LNK1104 cannot open file 'LIBCD.lib'

(I don't think this is an error specific to VolPack, I think it applies to any lib compiled under VC 6 and then linked to in a later version of VS, so I think the question isn't too specific for StackOverflow.)

I found this: https://support.microsoft.com/en-us/help/154753/description-of-the-default-c-and-c-libraries-that-a-program-will-link, which explains why it's using that lib, but I don't know what to do about it in VS 6. I don't see an option regarding multithreading to change to make it use a different lib, and a quick Google search reveals that VS 6 doesn't support multithreading.

I did find this: How to solve "cannot open file 'LIBCD.lib' " in visual studio 2008?, but I'm not sure the solution is relevant to my issue because the string "GLUI" occurs nowhere in the lib I'm trying to link to. Even if it is the solution to my problem, I don't know where to get the source code for GLUI, exactly what changes I need to make to the makefile, or how to make VS 6 use the new recompiled GLUI, whatever that is.

The next solution was basically to tell the linker to ignore LIBCD.lib, but that gave me other errors. I found this: https://www.youtube.com/watch?v=zKrggjsgQx4, which basically says to ignore LIBCD.lib and then change the runtime library to multi-threaded debug, but that gave me errors too.

The errors I get when trying to compile VolPack under VS 2019 are all "potentially unitialized local pointer variable", so it's probably some simple modifications to get it to compile under VS 2019, but I'm not an expert at C and I don't want to deal with the headache of trying to figure out how to modify the program and of potentially breaking it. So f anybody knows an easy way to solve that problem that might work too. Thanks.


Solution

  • When you use a static library that has dependencies on other libraries then the compiler is going to complain if it can not find those other libraries.

    The difference between Microsoft Visual Studio 6.x and Visual Studio 2019 is immense. As I've ported old code, both C and C++, from 6.x to VS 2015 I have had to make a number of source code changes to allow compiles to work due to the improvements of Microsoft in its adherence to the standards as well as supporting new versions of the standards, some of which deprecate previously supported constructs.

    See this post about compatibility between versions, Library ABI compatibility between versions of Visual Studio See as well:

    Binary compatibility between VS2017 and VS2015

    ABI-Compatibility of visual studio c-libraries

    And this blog posting from Microsoft about the release of Visual Studio 2019 dated 2019 says:

    Visual Studio 2019 version 16.0 is now available and is binary compatible with VS 2015/2017. In this first release of VS 2019, we’ve implemented more compiler and library features from the C++20 Working Paper, implemented more overloads (C++17’s “final boss”), and fixed many correctness, performance, and throughput issues. Here’s a list of the C++17/20 compiler/library feature work and the library fixes. (As usual, many compiler bugs were also fixed, but they aren’t listed here; compiler fixes tend to be specific to certain arcane code patterns. We recently blogged about compiler optimization and build throughput improvements in VS 2019, and we maintain a documentation page about compiler conformance improvements in VS 2019.)

    I don't see any other recourse than to work with the source to make it compatible with Visual Studio 2019. If you look, you may find that your level of expertise with C is sufficient for to implement some of the suggestions below.

    The best course of action would seem to be to make the necessary source code changes to the library so that it will compile correctly under Visual Studio 2019.

    The best course of action is to review the source code in each place where the uninitialized pointer error is being found and correct the source code so that the error is no longer generated. The programmers who previously worked in those areas of code obviously left out a potential flow of control probably due to their expectation that the missing code would never be executed based on the assumptions of how the function would be used. Most likely any such functions are complex and may need to be refactored.

    Most often I have seen this type of missing flow being due to a switch statement missing a default: to capture the event of the switch variable not being one of the specified case values. It may also be due to an if statement that is a series of else if without a final else to capture any other possible condition. Or it may also be due to a loop which has a break statement before the pointer variable is initialized or which uses a continue statement to skip where the variable is initialized.

    In most cases these issues are due to functions with low cohesion and/or are overly complex and large with maintenance actions over time introducing these kinds of problems.

    A less desirable practice for the error of a potentially uninitialized pointer is to just initialize with some appropriate value. You can jump to where the error is, click on the variable and go to where it is defined, and then set it to an appropriate value. In most cases a value of NULL for pointers is safest because if it stays NULL and is used without being modified to a correct value, your application should crash letting you know there is a problem.

    By initializing to NULL you are assuming the previous programmers knew what they were doing and the possible flow(s) detected by the compiler that would leave the variable unchanged to a proper value will never happen due to the logic.

    And should the uninitialized pointer flow happen, you will find out when the application crashes. Unfortunately tracing back to the origin of the crash may be difficult.

    You can use assert and other tests within the code to create a break point should you be debugging or to generate an exception, if it is C++, which may be more informative than just crashing. So adding such a test just before the line of source code generating the error, checking for NULL in the test before using the pointer may be helpful.

    Or if the function has a status code indicating if it worked or not and any errors along with some way of returning an error status then the most efficient thing would be to use that error reporting at the pointer where the potentially uninitialized pointer error is being generated should the sanity check fail.

    However if you can discern a safe default value, you may want to use that instead. Discerning a safe value will require reviewing the source code to determine what the safe default value should be. Sometimes such a safe value can be the address of a variable of the appropriate type initialized to zero.

    Warning: if the address in the pointer is being returned, do not use the address of a variable local to the function. When the function returns that address will no longer be valid leading to Undefined Behavior.

    Warning 2: if the address in the pointer is expected to have been allocated using malloc() or new or similar memory allocator then you must use the same mechanism so that when some code decides to deallocate the memory using free() or delete then it will work.

    This review will require reading the source code of the function where the uninitialized pointer is being used if the value of the pointer is localized to the function itself. If the pointer is returned by the function, the value exported by the function to a user of the function, then you will also need to review the source code where the function is used in order to determine an appropriate default value.

    So what I suggest you do is that every place where you do the initialization, you add a unique identifying comment (something along the lines of "Inhahe fix uninitialized pointer error 06/10/2020") to the line so that you can then do a search to find these at a later time and then go back into the problematic code and actually fix the compiler error by refactoring or changing the code to eliminate the possible uninitialized pointer error.

    And before you do anything get the source under version control of some kind.