Selecting implementations of C++ functions using the linker
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I would like to test C++ functions in a piece of code by swapping them
one by one for ones that are known to work in a working context, where the swapping is done using the linker. (I use C++ with GCC under linux.) Unfortunately I do not know enough about how to drive the linker to know how to do this or even if it is possible.
For me, the main reason is to test students' code against a teacher's
model solution, though I can imagine plenty of other cases where such
methods may be of interest. Note that the students' source code is
available and can be compiled in any way I like, but this source
cannot be edited. However, the teacher's code can be modified as
needed.
There follows a simple example that shows the idea.
Here is, the teacher's code, in which the functions can call each
other in ways similar to that shown. All functions here are assumed
to meet their specifications exactly.
#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;
A typical student's code, attempting to meet the same specifications,
to be tested. In my case a "main", several #includes, and "using
namespace std;" would be expected.
#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;
I want to swap each of the teacher's functions one by one to test each
student function individually.
Here is one attempt, in this case testing the student's 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
and the result I would expect is
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(4) returned 82
unfortunately, I get:
strip: not stripping symbol `_Z1fi' because it is named in a relocation
I have tried doing something similar with .so libraries instead. The
error message to strip disappears, but unfortunately this time the
teacher main calls the teacher g that I had tried to remove.
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
giving
in teacher-main()
in teacher-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 91
Any suggestions? Is this even possible? If not, is there any way
round to do the same thing? As said I cannot edit student.cpp, but I
could #include it from other source code.
Thanks
Richard
c++ linker ld
|
show 4 more comments
I would like to test C++ functions in a piece of code by swapping them
one by one for ones that are known to work in a working context, where the swapping is done using the linker. (I use C++ with GCC under linux.) Unfortunately I do not know enough about how to drive the linker to know how to do this or even if it is possible.
For me, the main reason is to test students' code against a teacher's
model solution, though I can imagine plenty of other cases where such
methods may be of interest. Note that the students' source code is
available and can be compiled in any way I like, but this source
cannot be edited. However, the teacher's code can be modified as
needed.
There follows a simple example that shows the idea.
Here is, the teacher's code, in which the functions can call each
other in ways similar to that shown. All functions here are assumed
to meet their specifications exactly.
#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;
A typical student's code, attempting to meet the same specifications,
to be tested. In my case a "main", several #includes, and "using
namespace std;" would be expected.
#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;
I want to swap each of the teacher's functions one by one to test each
student function individually.
Here is one attempt, in this case testing the student's 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
and the result I would expect is
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(4) returned 82
unfortunately, I get:
strip: not stripping symbol `_Z1fi' because it is named in a relocation
I have tried doing something similar with .so libraries instead. The
error message to strip disappears, but unfortunately this time the
teacher main calls the teacher g that I had tried to remove.
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
giving
in teacher-main()
in teacher-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 91
Any suggestions? Is this even possible? If not, is there any way
round to do the same thing? As said I cannot edit student.cpp, but I
could #include it from other source code.
Thanks
Richard
c++ linker ld
What about capturing the output of the teacher and student programs separately and comparing them with a tool likedifformeld(graphical)?
– Galik
Nov 15 '18 at 14:43
That doesn't do what I am asking for. I want to test the result of the student's g() when it calls the teachers f(). In a learning environment I want to be able to give a student credit for correctly coding g() even though his/her f() is incorrect.
– user2444353
Nov 15 '18 at 14:46
1
Is there any reason why students need to codemainin their file? Can you ask them to code onlyfandg, and then link yourself with relevant teacher'smain? Or at least require them to submit two files, one withfandg, and the other withmain.
– Petr
Nov 15 '18 at 14:55
2
It is certainly possible to ask the students to do their coding in a particular way. In my class they are all raw beginners and anything but the very simplest instructions will be misunderstood and ignored by a large proportion of them, leading to a large amount of teacher time being required to manually edit the student programs so they comply. It is difficult enough to emphasise their functions have to be called f and g and not "myf" and "myg" and that if the specification says "int" then "double" will not do.
– user2444353
Nov 15 '18 at 15:05
1
Stripping the source code of itsmainlike 99+% of the time sounds simple enough with a regex. It's not like students will write stuff likestd::type_identity<int>::type main(std::void_t<decltype(42)>).
– Passer By
Nov 15 '18 at 15:07
|
show 4 more comments
I would like to test C++ functions in a piece of code by swapping them
one by one for ones that are known to work in a working context, where the swapping is done using the linker. (I use C++ with GCC under linux.) Unfortunately I do not know enough about how to drive the linker to know how to do this or even if it is possible.
For me, the main reason is to test students' code against a teacher's
model solution, though I can imagine plenty of other cases where such
methods may be of interest. Note that the students' source code is
available and can be compiled in any way I like, but this source
cannot be edited. However, the teacher's code can be modified as
needed.
There follows a simple example that shows the idea.
Here is, the teacher's code, in which the functions can call each
other in ways similar to that shown. All functions here are assumed
to meet their specifications exactly.
#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;
A typical student's code, attempting to meet the same specifications,
to be tested. In my case a "main", several #includes, and "using
namespace std;" would be expected.
#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;
I want to swap each of the teacher's functions one by one to test each
student function individually.
Here is one attempt, in this case testing the student's 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
and the result I would expect is
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(4) returned 82
unfortunately, I get:
strip: not stripping symbol `_Z1fi' because it is named in a relocation
I have tried doing something similar with .so libraries instead. The
error message to strip disappears, but unfortunately this time the
teacher main calls the teacher g that I had tried to remove.
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
giving
in teacher-main()
in teacher-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 91
Any suggestions? Is this even possible? If not, is there any way
round to do the same thing? As said I cannot edit student.cpp, but I
could #include it from other source code.
Thanks
Richard
c++ linker ld
I would like to test C++ functions in a piece of code by swapping them
one by one for ones that are known to work in a working context, where the swapping is done using the linker. (I use C++ with GCC under linux.) Unfortunately I do not know enough about how to drive the linker to know how to do this or even if it is possible.
For me, the main reason is to test students' code against a teacher's
model solution, though I can imagine plenty of other cases where such
methods may be of interest. Note that the students' source code is
available and can be compiled in any way I like, but this source
cannot be edited. However, the teacher's code can be modified as
needed.
There follows a simple example that shows the idea.
Here is, the teacher's code, in which the functions can call each
other in ways similar to that shown. All functions here are assumed
to meet their specifications exactly.
#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;
A typical student's code, attempting to meet the same specifications,
to be tested. In my case a "main", several #includes, and "using
namespace std;" would be expected.
#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;
I want to swap each of the teacher's functions one by one to test each
student function individually.
Here is one attempt, in this case testing the student's 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
and the result I would expect is
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(4) returned 82
unfortunately, I get:
strip: not stripping symbol `_Z1fi' because it is named in a relocation
I have tried doing something similar with .so libraries instead. The
error message to strip disappears, but unfortunately this time the
teacher main calls the teacher g that I had tried to remove.
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
giving
in teacher-main()
in teacher-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 91
Any suggestions? Is this even possible? If not, is there any way
round to do the same thing? As said I cannot edit student.cpp, but I
could #include it from other source code.
Thanks
Richard
c++ linker ld
c++ linker ld
asked Nov 15 '18 at 14:35
user2444353user2444353
312
312
What about capturing the output of the teacher and student programs separately and comparing them with a tool likedifformeld(graphical)?
– Galik
Nov 15 '18 at 14:43
That doesn't do what I am asking for. I want to test the result of the student's g() when it calls the teachers f(). In a learning environment I want to be able to give a student credit for correctly coding g() even though his/her f() is incorrect.
– user2444353
Nov 15 '18 at 14:46
1
Is there any reason why students need to codemainin their file? Can you ask them to code onlyfandg, and then link yourself with relevant teacher'smain? Or at least require them to submit two files, one withfandg, and the other withmain.
– Petr
Nov 15 '18 at 14:55
2
It is certainly possible to ask the students to do their coding in a particular way. In my class they are all raw beginners and anything but the very simplest instructions will be misunderstood and ignored by a large proportion of them, leading to a large amount of teacher time being required to manually edit the student programs so they comply. It is difficult enough to emphasise their functions have to be called f and g and not "myf" and "myg" and that if the specification says "int" then "double" will not do.
– user2444353
Nov 15 '18 at 15:05
1
Stripping the source code of itsmainlike 99+% of the time sounds simple enough with a regex. It's not like students will write stuff likestd::type_identity<int>::type main(std::void_t<decltype(42)>).
– Passer By
Nov 15 '18 at 15:07
|
show 4 more comments
What about capturing the output of the teacher and student programs separately and comparing them with a tool likedifformeld(graphical)?
– Galik
Nov 15 '18 at 14:43
That doesn't do what I am asking for. I want to test the result of the student's g() when it calls the teachers f(). In a learning environment I want to be able to give a student credit for correctly coding g() even though his/her f() is incorrect.
– user2444353
Nov 15 '18 at 14:46
1
Is there any reason why students need to codemainin their file? Can you ask them to code onlyfandg, and then link yourself with relevant teacher'smain? Or at least require them to submit two files, one withfandg, and the other withmain.
– Petr
Nov 15 '18 at 14:55
2
It is certainly possible to ask the students to do their coding in a particular way. In my class they are all raw beginners and anything but the very simplest instructions will be misunderstood and ignored by a large proportion of them, leading to a large amount of teacher time being required to manually edit the student programs so they comply. It is difficult enough to emphasise their functions have to be called f and g and not "myf" and "myg" and that if the specification says "int" then "double" will not do.
– user2444353
Nov 15 '18 at 15:05
1
Stripping the source code of itsmainlike 99+% of the time sounds simple enough with a regex. It's not like students will write stuff likestd::type_identity<int>::type main(std::void_t<decltype(42)>).
– Passer By
Nov 15 '18 at 15:07
What about capturing the output of the teacher and student programs separately and comparing them with a tool like
diff or meld(graphical)?– Galik
Nov 15 '18 at 14:43
What about capturing the output of the teacher and student programs separately and comparing them with a tool like
diff or meld(graphical)?– Galik
Nov 15 '18 at 14:43
That doesn't do what I am asking for. I want to test the result of the student's g() when it calls the teachers f(). In a learning environment I want to be able to give a student credit for correctly coding g() even though his/her f() is incorrect.
– user2444353
Nov 15 '18 at 14:46
That doesn't do what I am asking for. I want to test the result of the student's g() when it calls the teachers f(). In a learning environment I want to be able to give a student credit for correctly coding g() even though his/her f() is incorrect.
– user2444353
Nov 15 '18 at 14:46
1
1
Is there any reason why students need to code
main in their file? Can you ask them to code only f and g, and then link yourself with relevant teacher's main? Or at least require them to submit two files, one with f and g, and the other with main.– Petr
Nov 15 '18 at 14:55
Is there any reason why students need to code
main in their file? Can you ask them to code only f and g, and then link yourself with relevant teacher's main? Or at least require them to submit two files, one with f and g, and the other with main.– Petr
Nov 15 '18 at 14:55
2
2
It is certainly possible to ask the students to do their coding in a particular way. In my class they are all raw beginners and anything but the very simplest instructions will be misunderstood and ignored by a large proportion of them, leading to a large amount of teacher time being required to manually edit the student programs so they comply. It is difficult enough to emphasise their functions have to be called f and g and not "myf" and "myg" and that if the specification says "int" then "double" will not do.
– user2444353
Nov 15 '18 at 15:05
It is certainly possible to ask the students to do their coding in a particular way. In my class they are all raw beginners and anything but the very simplest instructions will be misunderstood and ignored by a large proportion of them, leading to a large amount of teacher time being required to manually edit the student programs so they comply. It is difficult enough to emphasise their functions have to be called f and g and not "myf" and "myg" and that if the specification says "int" then "double" will not do.
– user2444353
Nov 15 '18 at 15:05
1
1
Stripping the source code of its
main like 99+% of the time sounds simple enough with a regex. It's not like students will write stuff like std::type_identity<int>::type main(std::void_t<decltype(42)>).– Passer By
Nov 15 '18 at 15:07
Stripping the source code of its
main like 99+% of the time sounds simple enough with a regex. It's not like students will write stuff like std::type_identity<int>::type main(std::void_t<decltype(42)>).– Passer By
Nov 15 '18 at 15:07
|
show 4 more comments
3 Answers
3
active
oldest
votes
This somewhat violates your requirements, but I would suggest you to change the expected form of student's code. Do not require them to code main, or ask then to code main in a separate compilation unit, or just ask them to rename their main to say main_ before submission. Or just add #define main main_ to the top of student's code after the submission before the compilation; for simple tasks this will be enough.
After that, you do not need to strip anything from compiled code. Just place all your functions to namespace teacher, write your own main that will do all needed work, and link all code together. Change and recompile your code to call teacher::f for your function, or ::f for the student's function.
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
add a comment |
I think the only possible solution is to separate it to two files:
1st file should be common for teacher and student and may contain both main and f + forward declaration for g:
common file: (common.cpp)
#include <iostream>
using namespace std;
int g(int x) ;
int f(int x)
cout << "in teacher-f(" << x << ")" << endl;
return 46;
int main()
cout << "in teacher-main()" << endl;
int x = 2;
int y = g(x);
cout << "g(" << x << ") returned " << y << endl;
2nd file should contain the g method (+ forward declaration to f):
teacher(teacher.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in teacher-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 91;
student (student.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in student-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 82;
now you can compile teacher from common.cpp + teacher.cpp
g++ -o teacher common.cpp teacher.cpp
and student from common.cpp + student.cpp
g++ -o student common.cpp student.cpp
The common.cpp can be even replaced by a static or shared library and you can add a header instead of the forward declaration of f.
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
add a comment |
This was from Lawrence and answers my question. I can't say about portability etc.
g++ -c student.cpp
g++ -c teacher.cpp
strip -N main student.o
objcopy -W _Z1fi student.o
objcopy -W _Z1gi teacher.o
g++ -o final teacher.o student.o
./final
giving the expected
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 82
Thanks!
PS I must have made a typo first time I tried it, or else the order of stripping and weakening is important... my comment to say this objcopy -W idea doesn't work has now been deleted. The above has been tested a few times now.
1
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53321778%2fselecting-implementations-of-c-functions-using-the-linker%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
This somewhat violates your requirements, but I would suggest you to change the expected form of student's code. Do not require them to code main, or ask then to code main in a separate compilation unit, or just ask them to rename their main to say main_ before submission. Or just add #define main main_ to the top of student's code after the submission before the compilation; for simple tasks this will be enough.
After that, you do not need to strip anything from compiled code. Just place all your functions to namespace teacher, write your own main that will do all needed work, and link all code together. Change and recompile your code to call teacher::f for your function, or ::f for the student's function.
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
add a comment |
This somewhat violates your requirements, but I would suggest you to change the expected form of student's code. Do not require them to code main, or ask then to code main in a separate compilation unit, or just ask them to rename their main to say main_ before submission. Or just add #define main main_ to the top of student's code after the submission before the compilation; for simple tasks this will be enough.
After that, you do not need to strip anything from compiled code. Just place all your functions to namespace teacher, write your own main that will do all needed work, and link all code together. Change and recompile your code to call teacher::f for your function, or ::f for the student's function.
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
add a comment |
This somewhat violates your requirements, but I would suggest you to change the expected form of student's code. Do not require them to code main, or ask then to code main in a separate compilation unit, or just ask them to rename their main to say main_ before submission. Or just add #define main main_ to the top of student's code after the submission before the compilation; for simple tasks this will be enough.
After that, you do not need to strip anything from compiled code. Just place all your functions to namespace teacher, write your own main that will do all needed work, and link all code together. Change and recompile your code to call teacher::f for your function, or ::f for the student's function.
This somewhat violates your requirements, but I would suggest you to change the expected form of student's code. Do not require them to code main, or ask then to code main in a separate compilation unit, or just ask them to rename their main to say main_ before submission. Or just add #define main main_ to the top of student's code after the submission before the compilation; for simple tasks this will be enough.
After that, you do not need to strip anything from compiled code. Just place all your functions to namespace teacher, write your own main that will do all needed work, and link all code together. Change and recompile your code to call teacher::f for your function, or ::f for the student's function.
answered Nov 15 '18 at 15:09
PetrPetr
8,28711843
8,28711843
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
add a comment |
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
Hi Petr, Once again, this is indeed part of the bodged hacked "solution" that I currently employ and am trying to improve. I am fine with the macro #define hack for main. The main problem is that I have to modify the student code throughout and replace all student function calls to f() or g() or any other of the functions in the assessed set to teacher::f() and teacher::g() etc. This is a bit messy but can (and does) break badly if students use unexpected syntax or use multiple-function solutions to problems when I expect only one function.
– user2444353
Nov 15 '18 at 15:28
add a comment |
I think the only possible solution is to separate it to two files:
1st file should be common for teacher and student and may contain both main and f + forward declaration for g:
common file: (common.cpp)
#include <iostream>
using namespace std;
int g(int x) ;
int f(int x)
cout << "in teacher-f(" << x << ")" << endl;
return 46;
int main()
cout << "in teacher-main()" << endl;
int x = 2;
int y = g(x);
cout << "g(" << x << ") returned " << y << endl;
2nd file should contain the g method (+ forward declaration to f):
teacher(teacher.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in teacher-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 91;
student (student.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in student-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 82;
now you can compile teacher from common.cpp + teacher.cpp
g++ -o teacher common.cpp teacher.cpp
and student from common.cpp + student.cpp
g++ -o student common.cpp student.cpp
The common.cpp can be even replaced by a static or shared library and you can add a header instead of the forward declaration of f.
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
add a comment |
I think the only possible solution is to separate it to two files:
1st file should be common for teacher and student and may contain both main and f + forward declaration for g:
common file: (common.cpp)
#include <iostream>
using namespace std;
int g(int x) ;
int f(int x)
cout << "in teacher-f(" << x << ")" << endl;
return 46;
int main()
cout << "in teacher-main()" << endl;
int x = 2;
int y = g(x);
cout << "g(" << x << ") returned " << y << endl;
2nd file should contain the g method (+ forward declaration to f):
teacher(teacher.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in teacher-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 91;
student (student.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in student-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 82;
now you can compile teacher from common.cpp + teacher.cpp
g++ -o teacher common.cpp teacher.cpp
and student from common.cpp + student.cpp
g++ -o student common.cpp student.cpp
The common.cpp can be even replaced by a static or shared library and you can add a header instead of the forward declaration of f.
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
add a comment |
I think the only possible solution is to separate it to two files:
1st file should be common for teacher and student and may contain both main and f + forward declaration for g:
common file: (common.cpp)
#include <iostream>
using namespace std;
int g(int x) ;
int f(int x)
cout << "in teacher-f(" << x << ")" << endl;
return 46;
int main()
cout << "in teacher-main()" << endl;
int x = 2;
int y = g(x);
cout << "g(" << x << ") returned " << y << endl;
2nd file should contain the g method (+ forward declaration to f):
teacher(teacher.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in teacher-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 91;
student (student.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in student-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 82;
now you can compile teacher from common.cpp + teacher.cpp
g++ -o teacher common.cpp teacher.cpp
and student from common.cpp + student.cpp
g++ -o student common.cpp student.cpp
The common.cpp can be even replaced by a static or shared library and you can add a header instead of the forward declaration of f.
I think the only possible solution is to separate it to two files:
1st file should be common for teacher and student and may contain both main and f + forward declaration for g:
common file: (common.cpp)
#include <iostream>
using namespace std;
int g(int x) ;
int f(int x)
cout << "in teacher-f(" << x << ")" << endl;
return 46;
int main()
cout << "in teacher-main()" << endl;
int x = 2;
int y = g(x);
cout << "g(" << x << ") returned " << y << endl;
2nd file should contain the g method (+ forward declaration to f):
teacher(teacher.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in teacher-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 91;
student (student.cpp):
#include <iostream>
using namespace std;
int f(int x);
int g(int x)
cout << "in student-g(" << x << ")" << endl;
int y = f(x);
cout << "f(" << x << ") returned " << y << endl;
return 82;
now you can compile teacher from common.cpp + teacher.cpp
g++ -o teacher common.cpp teacher.cpp
and student from common.cpp + student.cpp
g++ -o student common.cpp student.cpp
The common.cpp can be even replaced by a static or shared library and you can add a header instead of the forward declaration of f.
answered Nov 15 '18 at 15:51
SHRSHR
6,06872544
6,06872544
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
add a comment |
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
Thanks, but it doesn't meet my requirements nor answer the original question. It's too difficult to automatically edit foreign and possibly very unpleasant student code to do it this way.
– user2444353
Nov 15 '18 at 16:15
add a comment |
This was from Lawrence and answers my question. I can't say about portability etc.
g++ -c student.cpp
g++ -c teacher.cpp
strip -N main student.o
objcopy -W _Z1fi student.o
objcopy -W _Z1gi teacher.o
g++ -o final teacher.o student.o
./final
giving the expected
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 82
Thanks!
PS I must have made a typo first time I tried it, or else the order of stripping and weakening is important... my comment to say this objcopy -W idea doesn't work has now been deleted. The above has been tested a few times now.
1
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
add a comment |
This was from Lawrence and answers my question. I can't say about portability etc.
g++ -c student.cpp
g++ -c teacher.cpp
strip -N main student.o
objcopy -W _Z1fi student.o
objcopy -W _Z1gi teacher.o
g++ -o final teacher.o student.o
./final
giving the expected
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 82
Thanks!
PS I must have made a typo first time I tried it, or else the order of stripping and weakening is important... my comment to say this objcopy -W idea doesn't work has now been deleted. The above has been tested a few times now.
1
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
add a comment |
This was from Lawrence and answers my question. I can't say about portability etc.
g++ -c student.cpp
g++ -c teacher.cpp
strip -N main student.o
objcopy -W _Z1fi student.o
objcopy -W _Z1gi teacher.o
g++ -o final teacher.o student.o
./final
giving the expected
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 82
Thanks!
PS I must have made a typo first time I tried it, or else the order of stripping and weakening is important... my comment to say this objcopy -W idea doesn't work has now been deleted. The above has been tested a few times now.
This was from Lawrence and answers my question. I can't say about portability etc.
g++ -c student.cpp
g++ -c teacher.cpp
strip -N main student.o
objcopy -W _Z1fi student.o
objcopy -W _Z1gi teacher.o
g++ -o final teacher.o student.o
./final
giving the expected
in teacher-main()
in student-g(2)
in teacher-f(2)
f(2) returned 46
g(2) returned 82
Thanks!
PS I must have made a typo first time I tried it, or else the order of stripping and weakening is important... my comment to say this objcopy -W idea doesn't work has now been deleted. The above has been tested a few times now.
edited Nov 15 '18 at 16:17
answered Nov 15 '18 at 16:09
user2444353user2444353
312
312
1
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
add a comment |
1
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
1
1
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
I am also not a linker expert but my understanding is that marking a symbol as 'weak' allows it to be overridden when the linker does symbol resolution. By default, a symbol (function or global / static var) is strong.
– Lawrence
Nov 15 '18 at 16:21
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53321778%2fselecting-implementations-of-c-functions-using-the-linker%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What about capturing the output of the teacher and student programs separately and comparing them with a tool like
difformeld(graphical)?– Galik
Nov 15 '18 at 14:43
That doesn't do what I am asking for. I want to test the result of the student's g() when it calls the teachers f(). In a learning environment I want to be able to give a student credit for correctly coding g() even though his/her f() is incorrect.
– user2444353
Nov 15 '18 at 14:46
1
Is there any reason why students need to code
mainin their file? Can you ask them to code onlyfandg, and then link yourself with relevant teacher'smain? Or at least require them to submit two files, one withfandg, and the other withmain.– Petr
Nov 15 '18 at 14:55
2
It is certainly possible to ask the students to do their coding in a particular way. In my class they are all raw beginners and anything but the very simplest instructions will be misunderstood and ignored by a large proportion of them, leading to a large amount of teacher time being required to manually edit the student programs so they comply. It is difficult enough to emphasise their functions have to be called f and g and not "myf" and "myg" and that if the specification says "int" then "double" will not do.
– user2444353
Nov 15 '18 at 15:05
1
Stripping the source code of its
mainlike 99+% of the time sounds simple enough with a regex. It's not like students will write stuff likestd::type_identity<int>::type main(std::void_t<decltype(42)>).– Passer By
Nov 15 '18 at 15:07