为 C++ 编译时未找到符号,但为 C 找到了符号
Posted
技术标签:
【中文标题】为 C++ 编译时未找到符号,但为 C 找到了符号【英文标题】:Symbols not found when compiling for C++, but found for C 【发布时间】:2014-08-07 23:59:43 【问题描述】:我正在尝试在 C++ 下的 OS X 上编译一些代码,但我遇到了一些未找到符号的问题。
当我为 C 编译时,它工作得很好:
g++ -x c -fobjc-arc -fobjc-link-runtime -framework IOKit -framework CoreFoundation -framework Foundation kextstat/main.cpp -o ks
当我将-x c
更改为-x c++
时,突然找不到符号:
$ g++ -x c++ -fobjc-arc -fobjc-link-runtime -framework IOKit -framework CoreFoundation -framework Foundation kextstat/main.cpp -o ks
Undefined symbols for architecture x86_64:
"OSKextCopyLoadedKextInfo(__CFArray const*, __CFArray const*)", referenced from:
_main in main-66ed7f.o
"kas_info(int, void*, unsigned long*)", referenced from:
print_kextstat(__CFDictionary const*) in main-66ed7f.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我删除了对这些符号的引用并获得了 C++ 版本进行编译,以便我可以检查每个二进制文件链接的库是否存在不一致,但它们完全相同:
$ otool -L ks_cxx
ks_cxx:
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.17.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1056.13.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
$ otool -L ks_c
ks_c:
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.17.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1056.13.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
这是main.cpp
的代码清单:
#import <CoreFoundation/CoreFoundation.h>
#define KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR (0)
#define KAS_INFO_MAX_SELECTOR (1)
int kas_info(int selector, void *value, size_t *size);
extern CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
// Convert a CFString to a standard C string
char* cstring(CFStringRef s)
return ((char*)CFStringGetCStringPtr(s, kCFStringEncodingMacRoman));
void print_kextstat(CFDictionaryRef dict)
size_t kaslr_size = 0;
uint64_t kaslr_slide = 0;
kaslr_size = sizeof(kaslr_slide);
int ret = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &kaslr_slide, &kaslr_size);
if (ret != 0)
printf("[ERROR] Could not get kernel ASLR slide info from kas_info(). Errno: %d\n", errno);
exit(1);
printf("[INFO] Kernel ASLR slide is 0x%llx\n", kaslr_slide);
CFIndex count = CFDictionaryGetCount(dict);
CFIndex i, j;
void **keys;
void **values;
keys = (void **)malloc(sizeof(void *) * count);
values = (void **)malloc(sizeof(void *) * count);
CFDictionaryGetKeysAndValues(
dict,
(const void **)keys,
(const void **)values
);
printf("Index Refs Address Size Wired Name (Version) <Linked Against>\n");
for (i = 0; i < count; i++)
for (j = 0; j < count; j++)
int kextTag;
int refs;
unsigned long long address;
unsigned long long size;
unsigned long long wired;
char *name = cstring((CFStringRef)CFDictionaryGetValue((CFDictionaryRef)(values)[j], CFSTR("CFBundleIdentifier")));
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleLoadTag")),
kCFNumberSInt32Type,
&kextTag
);
if (kextTag != i)
continue;
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleRetainCount")),
kCFNumberSInt32Type,
&refs
);
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleLoadAddress")),
kCFNumberSInt64Type,
&address
);
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleLoadSize")),
kCFNumberSInt64Type,
&size
);
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleWiredSize")),
kCFNumberSInt64Type,
&wired
);
printf("%5d %4d 0x%-16llx 0x%-10llx 0x%-10llx %s (%s) ",
kextTag,
refs,
address + kaslr_slide,
size,
wired,
name,
cstring((CFStringRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("CFBundleVersion")))
);
CFArrayRef linkedAgainst = (CFArrayRef)CFDictionaryGetValue(
(CFDictionaryRef)values[j],
CFSTR("OSBundleDependencies")
);
if (linkedAgainst == NULL)
printf("\n");
continue;
CFIndex linkedCount = CFArrayGetCount(linkedAgainst);
int linked = 0;
CFMutableArrayRef marray = CFArrayCreateMutableCopy(
NULL,
linkedCount,
linkedAgainst
);
CFArraySortValues(
marray,
CFRangeMake(0, linkedCount),
(CFComparatorFunction)CFNumberCompare,
NULL
);
printf("<");
int l;
for (l = 0; l < linkedCount; l++)
CFNumberGetValue(
(CFNumberRef)CFArrayGetValueAtIndex(marray, l),
kCFNumberSInt32Type,
&linked
);
if (l)
printf(" ");
printf ("%d", linked);
printf(">\n");
int main (int argc, char **argv)
if (getuid() != 0)
printf("[ERROR] Please run me as root!\n");
exit(1);
print_kextstat(OSKextCopyLoadedKextInfo(NULL, NULL));
【问题讨论】:
好像在某处丢失了extern "C"
。
【参考方案1】:
您需要 extern "C"
围绕与使用 C ABI(而不是 C++ ABI)编译的代码链接的符号:
extern "C"
int kas_info(int selector, void *value, size_t *size);
CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
如果需要同时使用C和C++编译程序:
#ifdef __cplusplus
#define EXTERN_C_BEG extern "C"
#define EXTERN_C_END
#else
#define EXTERN_C_BEG
#define EXTERN_C_END
#endif
EXTERN_C_BEG
int kas_info(int selector, void *value, size_t *size);
CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
EXTERN_C_END
【讨论】:
以上是关于为 C++ 编译时未找到符号,但为 C 找到了符号的主要内容,如果未能解决你的问题,请参考以下文章
在 Xcode 项目中使用 C/C++ 库时未找到体系结构 x86_64 的符号
从 MS Visual C++ 编译器更改为英特尔 C++ 19.1 编译器时未解析的外部符号 __imp__fread