📄 tdump.txt
字号:
with C or assembly modules, the compiler must be notified that
the symbol is to be in the standard C style (non-encoded) rather
than employing C++ name-mangling (encoded). This is done by
prototyping the function as type extern "C". Here is a quick
example:
extern "C" int normal_c_func( float, int, char );
For an additional example, you may want to look at the header
files which came with the product. One such header file is
stdio.h.
o UNDEFINED SYMBOL: '_main' IN MODULE C0.ASM
Every DOS C program must contain a function called main(). This
is the first function executed in your program. The function name
must be all in lower case. If your program does not have one,
create one. If you are using multiple source files, the file that
contains the function main() must be one of the files listed in
the project.
Note that an underscore character '_' is prepended to all
external Borland C++ symbols.
In addition to an absent, misspelled or mis-cased symbol main,
there are two additional common causes:
o The "generate underbars" option is disabled.
o The Pascal calling Convention rather than the C calling
convention is selected.
o UNDEFINED SYMBOL LINKING A DLL
It is relatively simple to link a DLL to your source:
1) Create a .LIB from the .DLL using Borland's implib utility.
2) Include the .LIB in your project if you're using the IDE or
in your TLINK command if you're using the command-line
compiler or linker.
3) Turn case sensitive link ON.
4) Turn case sensitive exports ON.
The issues of linking C++ with C, assembly, or any other language
still apply. See the sections on linking C++, C, and assembly in
this document.
If the link still fails, the techniques in the section "Getting A
Closer Look" should help you resolve the problem.
o UNDEFINED SYMBOL: A PSEUDO REGISTER (i.e. _AX)
Pseudo registers are only allowed in the Borland C++ and ANSI
modes of the compiler. You can change this setting in the
Options | Compiler | Source menu.
o UNDEFINED SYMBOL: 'FIWRQQ'
Your program uses floating point routines directly (or
indirectly) and you have NONE selected for floating point. Or,
you are using TLINK and have forgotten to include EMU.LIB or
FP87.LIB on the command line.
o UNDEFINED SYMBOL: AN IOSTREAM CLASS MEMBER
If you are using the Integrated Development Environment, simply
turn off Options | Compiler | Code Generation | Unsigned
Characters.
If you are using the command-line compiler, simply remove the
'-K' option.
o UNDEFINED SYMBOL: 'abort()'
The sole purpose of abort is to print the error message
"Abnormal Program Termination"
and exit the program with an error code of 3. This function is
located in the startup code C0.ASM. Linker errors indicating that
abort() is an undefined symbol are only possible if the standard
startup code is not being linked into a project. Although this is
not a common C/C++ development practice, it is to be expected
when linking in code written other languages such Microsoft
Fortran, Clipper, or in cases where embedded systems are being
developed. To resolve the undefined symbol, extract the abort()
function from the startup code and make a separate object out of
it to be linked into the project.
o UNDEFINED SYMBOL: '_exitclean()'
There is a function called _exitclean which is new to Turbo C++.
Users moving from Turbo C 2.0 to Turbo C++ may encounter
_exitclean() as an undefined symbol at link time. _exitclean() is
defined in the Turbo C++ startup code. Users creating embedded
system (ROMable code), who do not use the standard Turbo C++
startup code, are likely to encounter _exitclean() as an
undefined symbol. These users can strip the function from the
C0.ASM file and create a separate .OBJ file which can be linked.
Another option would be to purchase the Borland C++ RTL source and make
the necessary adjustments.
o UNDEFINED SYMBOL: LLSH or SCOPY or FMUL or FDIV
The helper functions have changed their names from Turbo C 2.0 to
Turbo C++. This can lead to many undefined symbol issues.
When LLSH or SCOPY or FMUL or FDIV (note no underscores here)
appear as undefined symbols at link time, it is likely that an
object module or library has code generated a call to some helper
function from the Turbo C 2.0 libraries. The solution is to
simply recompile all objects from source. You can do this by
choosing Compile | BuildAll from the menu in the IDE.
o UNDEFINED SYMBOL: STATIC POINTER TO A CLASS MEMBER FUNCTION
Any static member of a class must be initialized--if not that
static member generates an undefined symbol error. The following
is an example of how to initialize a static pointer to class
member function of a class is initialized:
// When testing static member initialization, you must
// declare an instance of the class in a main function;
// otherwise, the linker has no reference which it must
// try to resolve, and the undefined symbol error will
// not be seen - thus you won't know that your
// initialization was in error.
#include <iostream.h>
// used to allow global initialization of static member pointer
typedef void (*fptr)();
// declare class containing static members
class First
{
public:
static fptr statptr;
};
// initialize static members of class First
fptr First::statptr = NULL;
int main(void) {
First fVar;
if (fVar.statptr == NULL)
cout << "fVar.statptr is NULL: " <<
fVar.statptr << endl;
return 0;
} // end of main()
o UNDEFINED SYMBOL: '_WSPRINTF'
Turn off the "Case-sensitive exports" and "Case-sensitive link"
options. If you are using the command linker, don't use the /c
switch. If you are invoking the linker from the BCC(x) command
line, use the -lc- switch. If you are using the IDE, go to the
linker options dialog box and turn off the case sensitivity
switch.
o UNDEFINED SYMBOL: 'fidrqq'
You will get an undefined symbol fidrqq when using the Integrated
Development Environment if you have the Options | Compiler | Code
Generation | More | Floating Point Option set to NONE and you are
using floating point arithmetic in your program. In order to best
solve this problem you must set the IDE option for Floating Point
to either the emulation choice or to the 80x87 choice. Note that
if you choose an 80x87 setting the application generated by the
compiler will require an 80x87 chip to be present at run-time.
Use this setting only when truly appropriate.
o UNDEFINED SYMBOL IN WINDOWS.H
Make sure you are using the windows.h file that came with Borland
C++, NOT the windows.h that came with the Microsoft Windows SDK.
If you include the Microsoft windows.h file you will get many
undefined symbols including WINMAIN in caps and translatemessage
in lower case. Use our windows.h file instead of Microsoft's when
you are using our compiler.
o UNDEFINED SYMBOL USING TCLASDLL.LIB
To use the DLL version of the container class library you must do
ALL of the following:
o Use the large memory model
o Use Smart Callbacks
o Turn case sensitive link ON
o Turn case sensitive exports ON
o Use the DLL version of the RTL
o Define _CLASSDLL
o UNDEFINED SYMBOL USING SELECTORS PROVIDED BY WINDOWS
If you are using _C000h or other selectors provided by Windows
and they are coming up as undefined symbols, perhaps you are
compiling in C++ mode and forgot to extern "C" them.
Programming in C:
extern WORD _C000h
Programming in C++:
extern "C" WORD _C000h
o UNDEFINED SYMBOL: 'ChangeSelector'
The Windows API function ChangeSelector() has the wrong name in
KERNEL.EXE for Windows 3.0, and therefore in IMPORT.LIB. The name
given to this function (and this is NOT a joke) is
PrestoChangoSelector().
Use PrestoChangoSelector() in your program in place of
ChangeSelector() and all will be well.
o UNDEFINED SYMBOLS USING THE OBJECTWINDOWS LIBRARY (OWL)
If you get any of the following the undefined symbols:
TApplication(unsigned char far *, unsigned int, unsigned int,
unsigned char far *, int )
and
TWindow::TWindow(TWindowsObject near *, unsigned char far *,
TModule near *)
and are using the DLL versions of OWL and the Class Library,
you must define _CLASSDLL in Options | Compiler | Code
Generation | defines combo box.
It could be because you have forced unsigned characters. The
functions in the .lib take signed characters and thus if you
compile to use unsigned characters, the symbols will not match.
Using the Integrated Development Environment be sure to turn
off Options | Compiler | Code Generation | Unsigned Characters.
If you are using the command line compiler be sure to remove
the -K option to solve this problem.
o UNDEFINED SYMBOL: 'Object::new(unsigned int)'
You forgot to link with the TCLASDLL.LIB file where it is
defined!
Basically the problem is that you are mixing both STATIC and
DYNAMIC LINK libraries into the application. You must use only
one or the other. If you are working in the IDE, change the
LINKER options section for libraries.
If you are using the dynamic link library, remember to set
_CLASSDLL and Build All.
If you are using the command line compiler and linker, just be
sure to specify the correct set of library files. For specific
information on the "correct set of library files" please see the
documentation included with the product as library names tend to
change from version to version.
GETTING A CLOSER LOOK
---------------------
Borland provides tools that you can use to determine exactly what the
linker is seeing when it is trying to match symbols: TDUMP and IMPDEF.
This section provides some simple techniques for using these utilities
to resolve undefined symbol errors.
o USING TDUMP TO RESOLVE UNDEFINED SYMBOLS
TDUMP can be used to list the symbols in a .OBJ or a static .LIB
that the linker is having trouble matching.
First, TDUMP the module that is trying to reference the symbol.
For example, if main.cpp is trying to access a function, myfunc()
in myfuncs.cpp and is getting "Undefined symbol myfunc() in
module main.cpp",
tdump -m -oiEXTDEF main.obj > main.ext
Then, TDUMP the module in which the symbol is defined.
tdump -m -oiPUBDEF myfuncs.obj > myfunc.pub
Using a text editor find the symbol associated with the error in
each file. If they are not the same, then you have verified that
the linker is correct in generating the error. You must check
your code and verify that the compiler is seeing the same
declaration for the symbol when each module is being compiled.
You can use TDUMP to look at a static .LIB file the same way you
look at an .OBJ. file.
tdump -m -oiPUBDEF mystatic.lib > mystatic.pub
To use TDUMP with an implib,
tdump -m -oiTHEADR mydll.lib > mydll.pub
You can also use IMPDEF to view the symbols exported by a DLL.
o USING IMPDEF TO RESOLVE UNDEFINED SYMBOLS IN A DLL
If you are trying to link a Borland generated DLL with another
language or product and are getting undefined symbol errors, you
should verify that the names or the ordinals that are being
exported by the DLL are the same as your application expects.
This can be done by generating a .DEF file with the utility
IMPDEF. For example, to create a .DEF file for MY.DLL,
impdef my.def my.dll
The .DEF file will have the exported symbol name and its ordinal
number. Remember that C++ mangles names. Your application must
expect the mangled symbol name to call the function in the DLL
properly. This can be a problem if the application automatically
uppercases the symbol name before trying to call the function. If
this is so, you must change the declaration of the function and
re-build your DLL.
===================================================================
3. Resolving Undefined Symbol linker messages
===================================================================
This section provides an overview of the Linking process and helps to
identify causes of 'unresolved external symbols'.
The code for printf() is in a module in the run time library. When you
call printf() in a C/C++ module, the compiler creates a record
(referred to as EXTDEF - EXTernal DEFinition) that indicates the call
to an external function. The linker then looks at that OBJ, along with
all the other modules and libraries specified and attempts to find
another module (.OBJ or .LIB) which defines/provides the
symbolprintf().
If the linker cannot resolve the call to printf(), the linker
generates an error indicating that printf() is an undefined symbol.
The error message, however, is very often not the result of leaving
out the module containing the symbol being looked for, but rather a
discrepancy between the name used by the caller (the C/C++ module
calling printf() in the case mentioned above) and the supplier (the
LIBRARY containing the code to printf() ).
The *real* name of any symbol is almost always different from the
name/identifier used by the programmer. For example, the *real* name
(by *real* name we mean the identifier used/generated by the tools) of
strcpy() is: '_strcpy()'. The *real* name of a symbol depends on the
various settings and options. The relevant settings are list below:
Calling Conventions:
> cdecl
> pascal
> fastcall
Compiler Settings:
> generate underbars
> unsigned chars ( C++ only )
Optimizations:
> Object Data Calling ( C++ only )
Virtual Table:
> Far Virtual Tables
Language used:
> C
> C++
> Assembly
Furthermore there are two options which affect how the linker attempts
to match symbols:
> Case sensitive link
> Case sensitive exports ( Windows only )
The following is a discussion of how the above mentioned options
affect the *real* name of symbols, hence the resolution of symbols.
Calling Conventions
-------------------
Borland and Turbo C++ both allow you to specify the default calling
convention. This default can be overridden by using the
'pascal', '_fastcall' or 'cdecl' keywords. Whether set globally or on
individual function instances, the calling convention affects the name
of functions. By default, when the compiler encounters a function
declared as,
int Foo( int ); // or: int cdecl Foo( int );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -