首页 > 解决方案 > 使用链接器选择 C++ 函数的实现

问题描述

我想在一段代码中测试 C++ 函数,方法是将它们一个一个地交换为已知在工作上下文中工作的函数,其中交换是使用链接器完成的。(我在 linux 下使用 C++ 和 GCC。)不幸的是,我对如何驱动链接器知之甚少,不知道如何做到这一点,或者即使它是可能的。

对我来说,主要原因是根据教师的模型解决方案测试学生的代码,尽管我可以想象很多其他情况可能会对这种方法感兴趣。请注意,学生的源代码是可用的,可以以我喜欢的任何方式编译,但不能编辑此源代码。但是,教师的代码可以根据需要进行修改。

下面是一个简单的例子来说明这个想法。

这是老师的代码,其中函数可以以类似于所示的方式相互调用。这里的所有功能都假定完全符合它们的规格。

#include <iostream>

using namespace std;

// model teacher program : main calls g which calls f

int f(int x) {
  cout << "in teacher-f(" << x << ")" << endl;
  return 46;
}

int g(int x) {
  cout << "in teacher-g(" << x << ")" << endl;
  int y = f(x);
  cout << "f(" << x << ") returned " << y << endl;  
  return 91;  
}

int main() {
  cout << "in teacher-main()" << endl;
  int x = 2;
  int y = g(x);
  cout << "g(" << x << ") returned " << y <<  endl;  
}

一个典型的学生代码,试图满足相同的规范,被测试。在我的例子中,一个“main”、几个#includes 和“using namespace std;” 将是预期的。

#include <iostream>

using namespace std;

// model student program : main calls g which calls f

int f(int x) {
  cout << "in student-f(" << x << ")" << endl;
  return 27;
}

int g(int x) {
  cout << "in student-g(" << x << ")" << endl;
  int y = f(x);
  cout << "f(" << x << ") returned " << y << endl;  
  return 82;  
}

int main() {
  cout << "in student-main()" << endl;
  int x = 4;
  int y = g(x);
  cout << "g(" << x << ") returned " << y <<  endl;  
  return 0;
}

我想一一交换每个老师的功能,以单独测试每个学生的功能。

这是一次尝试,在这种情况下测试学生的 g()

g++ -c student.cpp
# (this makes student.o)
# strip f() and main() from student.o:
strip -N main -N _Z1fi student.o

# similarly for teacher, but stripping g
g++ -c teacher.cpp
strip -N _Z1gi teacher.o
g++ -o final teacher.o student.o
./final

我期望的结果是

in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(4) returned 82

不幸的是,我得到:

strip: not stripping symbol `_Z1fi' because it is named in a relocation

我尝试用 .so 库做类似的事情。删除的错误消息消失了,但不幸的是这次老师主要调用了我试图删除的老师 g。

g++ -shared -fPIC -o student.so student.cpp
g++ -shared -fPIC -o teacher.so teacher.cpp 
strip -N main -N _Z1fi student.so
strip -N _Z1gi  teacher.so
g++ -o final teacher.so student.so
./final

给予

in teacher-main()
in teacher-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 91

有什么建议么?这甚至可能吗?如果没有,有没有办法做同样的事情?如前所述,我无法编辑 student.cpp,但我可以从其他源代码中#include 它。

谢谢理查德

标签: c++linkerld

解决方案


这有点违反您的要求,但我建议您更改学生代码的预期形式。不要要求他们编码main,或者要求他们在单独的编译单元中编码,或者只是要求main他们在提交之前重命名。或者只是在编译前提交后添加到学生代码的顶部;对于简单的任务,这就足够了。mainmain_#define main main_

之后,您不需要从已编译的代码中删除任何内容。只需将所有函数放入,编写自己函数来完成所有需要的工作,然后将所有代码链接在一起。更改并重新编译您的代码以调用您的函数或学生的函数。namespace teachermainteacher::f::f


推荐阅读