Chinaunix首页 | 论坛 | 博客
  • 博客访问: 70037
  • 博文数量: 26
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 310
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-02 16:13
文章分类

全部博文(26)

文章存档

2009年(18)

2008年(8)

我的朋友
最近访客

分类: C/C++

2008-08-21 14:15:25

就是C++编译器编译时会改变函数的名字,要加上一些东西。比如下面的fun函数编译后用nm看成了__1cDfun6Fi_i_
之所以改函数名是因为C++允许重载,比如int fun()和int fun(int),怎么都能用fun名字呢,可以根据参数类型每个取个新名字
如果C++代码要调用C库中的函数。在C++代码申明该函数时前面要加上extern "C"
如果在C中要调用C++中的函数,那么在C++代码定义该函数时需要用extern "C"
上面两条只是一般情况,实际上这个和语言没有关系,C++加上extern "C"后也和C语言一样没有name mangle。分析时关键是分别分析定义时有没有name mangle,使用时是有没有name mangle就可以。

下面是分别用C C++编译器编译是分别不进行和进行name mangle的实例,如果申明了extern "C" C++编译器也不进行name mangle

// 1.c
int fun(int a)
{
    return 0;
}
 
#ifdef __cplusplus
extern "C"
#endif
int externcfun()
{
    return 0;
}

CC -c 1.c -o mangle.o
cc -c 1.c -o nomangle.o

$nm mangle.o
mangle.o:
 
[Index]   Value      Size    Type  Bind  Other Shndx   Name
 
[3]     |         0|       0|SECT |LOCL |0    |5      |
[2]     |         0|       0|SECT |LOCL |0    |6      |
[1]     |         0|       0|FILE |LOCL |0    |ABS    |1.c
[5]     |        16|      36|FUNC |GLOB |0    |2      |__1cDfun6Fi_i_ // C++编译器进行了name mangle
[4]     |        72|      32|FUNC |GLOB |0    |2      |externcfun     // 申明了extern "C"时,即使C++编译器也不name mangle

$nm nomangle.o
nomangle.o:
 
[Index]   Value      Size    Type  Bind  Other Shndx   Name
 
[2]     |         0|       0|SECT |LOCL |0    |10     |
[3]     |         0|       0|SECT |LOCL |0    |9      |
[1]     |         0|       0|FILE |LOCL |0    |ABS    |1.c
[4]     |         0|       0|OBJT |LOCL |0    |3      |Bbss.bss
[5]     |         0|       0|OBJT |LOCL |0    |4      |Ddata.data
[6]     |         0|       0|OBJT |LOCL |0    |5      |Drodata.rodata
[7]     |        72|      32|FUNC |GLOB |0    |2      |externcfun
[8]     |        16|      36|FUNC |GLOB |0    |2      |fun          // c编译器没有name mangle


实际上这个和语言没有关系,主要看编译后的名字是什么,分析这类问题时按照编译生成的函数名。在看使用时和定义是是否一致
比如
// 1.cpp
int externcfun()
{
    return 0;
}
 
// main.cpp
extern externcfun();
 
int main()
{
    externcfun();
    return 0;
}
CC 1.cpp main.cpp没有问题

1.cpp 改成下面的,增加了extern "C" // 也就是都是C++编译器也会变异不过,因为定义时没有name mangle,链接使用时按照有name mangle找函数名字,当然找不到
extern "C" int externcfun()
{
    return 0;
}
再用上面的CC 1.cpp main.cpp编译报错
Undefined                       first referenced
 symbol                             in file
int externcfun()                main.o
ld: fatal: Symbol referencing errors. No output written to a.out

解决上面错误的方法是在main.cpp中申明externcfun时加上extern "C"
// main.cpp
extern "C" externcfun();
 
int main()
{
    externcfun();
    return 0;
}
阅读(902) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~