How static library in c++ work with name mangle? - c++

I ask this for understanding, In c there is no name mangling but c++ has. How this works for example say I have following files
exlib.hpp header file
exlib.cpp function implemented file
exapp.cpp main function using exlib
File exlib.hpp
#ifndef EXLIB
#define EXLIB
#include <iostream>
int sum(int, int);
int sum(int, int, int);
int sum(int, int, int, int);
#endif
File exlib.cpp
#include "exlib.hpp"
int sum(int a, int b)
{
std::cout << "In sum(int, int)" << std::endl;
return a + b;
}
int sum(int a, int b, int c)
{
std::cout << "In sum(int, int, int)" << std::endl;
return a + b + c;
}
int sum(int a, int b, int c, int d)
{
std::cout << "In sum(int, int, int, int)" << std::endl;
return a + b + c + d;
}
File exapp.cpp
#include "iostream"
#include "exlib.hpp"
int main()
{
std::cout << "Sum = " << sum(1, 1) << std::endl;
std::cout << "Sum = " << sum(2, 2, 2) << std::endl;
std::cout << "Sum = " << sum(3, 3, 3, 3) << std::endl;
}
Compile
$ g++ -c exlib.cpp
$ g++ exapp.cpp exlib.o -o exapp
$ ./exapp
sum in exlib.o are name mangled right ?
output:
Sum = In sum(int, int)
2
Sum = In sum(int, int, int)
6
Sum = In sum(int, int, int, int)
12
How sum correctly called after name mangle in main ?, There is any rules for name mangling that same name is replaced in main or How they identify?
All programming language mangle name in same way ?
Thanks.

While C++ offers Polymorphism (i.e. different things can be named equal in the same scope by using other features for distinguishing them), this is not supported by linkers (neither in statical nor dynamical linking). So, C++ compilers uses name mangling. (The other features are used to decorate the original identifier to produce a unique name.)
A C++ compiler compiles each C++ file (aka. translation unit) on its own. Hence, it is obvious that the name mangling has to be done in a unique, reproducible way by this compiler. I.e. the same declaration has to be mapped to the same symbol always.
Otherwise, it would be impossible for the linker to resolve symbols that were declared (only) in one file and defined in another.
However, there isn't a general name-mangling standard (e.g. as part of the C++ standard).
So, even on the same platform, the binary codes produced by two different compilers may be incompatible due to different name-mangling (as well as other details).
(For MS Visual C++, this makes even binaries from distinct versions incompatible.)
To overcome this, there exist Application Binary Interfaces (ABIs) for certain platforms (e.g. Linux).
One detail of an ABI is a standardized name-mangling.

Related

inline overload throwing errors c++

I am learning overloading an inline function.
In testing this code I can't compile with the following errors I can't understand as to what's wrong.
I tested it with only 1 inline function and works but a second breaks it. Can you please share some guidance:
Thank you for your help, Sergio
Compiler errors:
abs exception specification does not match previous declaration line 13
function long abs (const long) throw() already has body line 13
abs redefinition; different exception specification line 19
abs error in function definition or declaration; function not called line 30
abs error in function definition or declaration; function not called line 32
#include "pch.h"
#include <iostream>
using namespace std;
// Overload abs() three ways
inline int abs(int n)
{
cout << "In integer abs() \n";
return((n < 0) ? -n : n);
}
inline long abs(long n)
{
cout << "In long abs() \n";
return((n < 0) ? -n : n);
}
inline double abs(double n) {
cout << "In double abs() \n";
return ((n < 0 ? -n : n));
}
int main()
{
cout << "Absolute value of -10 Is ";
cout << abs(-10) << "\n";
cout << "Absolute value of -10L Is ";
cout << abs(-10L) << "\n";
cout << "Absolute value of -10.01 Is ";
cout << abs(-10.01) << "\n";
}
Your error is here:
using namespace std;
since this brings into the global namespace the definitions of the function overloads std::abs() (they are declared & defined in cmath which appears to be #included directly or indirectly into iostream), which then clash with your own definitions. The above statement (using namespace std;) is almost never a good idea, certainly not in a header file -- it is, unfortunately, commonly used in online coding contests to simplify code (no need for std::).
Btw, this has only do with inline inasmuch as the function definitions (not the declarations) clash, which must be declared inline in header files to obtain the proper linkage.
Precense of using namespace std; causes a conflict with ::std::abs function. However getting rid of using namespace std; will not solve the issue complitely.
The primary problem here is the use of a non-unique name for a function in global namespace. abs is a function from C standard library therefore you should not use this name for your own functions. Otherwise your may get an error if <stdlib.h> is included somewhere, or even a random Undefined Behavior because of ODR violation.
In order to prevent name conflicts in C++ you should typically define new functions in custom namespace:
n_sergio_solorzano_stuff
{
// Overload abs() three ways
inline int abs(int n)
{
...
or select globally unique names when you need to add something into global namespace:
inline int sergio_solorzano_stuff_abs(int n)

C++ struct testing

Hi I am new to C++ and testing a structure in a c++ code in dev-c++. but it is not compiling and giving errors .
It is working well with .h extensions in pre-processor directives in dev-c++. so i Dont think so it carries .h extension problems
#include<iostream.h>
#include<conio.h>
#include<iomanip.h>
struct car
{
const int MAX=10;
char model[MAX];
char spare_part[MAX];
float cost;
}
int main()
{
car BMW ;
BMW.model[MAX]="SLR-8 S";
BMW.spare_part[MAX]="SILENCER";
BMW.cost=175.56F;
cout << setw(50) << "\n\n WELCOME TO SHOWROOM" << endl << endl;
cout << "CAR MODEL: " << BMW.model[MAX] << endl;
cout << "SPARE PART: " << BMW.spare_part[MAX] << endl;
cout << "COST OF PRODUCT: " << BMW.cost[MAX] << endl;
return 0;
}
Compiler logs are:
Compiler: Default compiler
Executing g++.exe...
g++.exe "D:\cdev\projects\structure.cpp" -o "D:\cdev\projects\structure.exe" -I"D:\cdev\Dev-Cpp\lib\gcc\mingw32\3.4.2\include" -I"D:\cdev\Dev-Cpp\include\c++\3.4.2\backward" -I"D:\cdev\Dev-Cpp\include\c++\3.4.2\mingw32" -I"D:\cdev\Dev-Cpp\include\c++\3.4.2" -I"D:\cdev\Dev-Cpp\include" -L"D:\cdev\Dev-Cpp\lib"
In file included from D:/cdev/Dev-Cpp/include/c++/3.4.2/backward/iostream.h:31,
from D:\cdev\projects\structure.cpp:1:
D:/cdev/Dev-Cpp/include/c++/3.4.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
D:\cdev\projects\structure.cpp:6: error: ISO C++ forbids initialization of member `MAX'
D:\cdev\projects\structure.cpp:6: error: making `MAX' static
D:\cdev\projects\structure.cpp:13: error: new types may not be defined in a return type
D:\cdev\projects\structure.cpp:13: error: extraneous `int' ignored
D:\cdev\projects\structure.cpp:13: error: `main' must return `int'
D:\cdev\projects\structure.cpp: In function `int main(...)':
D:\cdev\projects\structure.cpp:16: error: `MAX' undeclared (first use this function)
D:\cdev\projects\structure.cpp:16: error: (Each undeclared identifier is reported only
once for each function it appears in.)
Execution terminated
Values in stuct should be initialized in a constructor, or should be static. Like:
struct car
{
static const int MAX=10;
...
There is a semicolon missing after the struct definition. It should be like:
struct car
{
static const int MAX=10;
char model[MAX];
char spare_part[MAX];
float cost;
};
Check your semicolons. One is required after the closing } of the struct.
Also, declare the MAX variable static, i.e.
{
static const int MAX=10;
but the compiler tells you that one quite nicely...
And the third error comes from the fact that you declare MAX inside car, you'd have to reference it accordingly as car::MAX. But actually, the whole BMW.model[MAX]="SLR-8 S"; statement doesn't really make sense. That would mean 'assign the string "SLR-8 S" to the character after the last one in BMW.model' (for a char[MAX], the valid indices start at 0, and go to (MAX-1)!). Best use std::string instead of char model[MAX], that's by far easier to handle! E.g.:
struct car
{
std::string model;
Then you can simply say
BMW.model="SLR-8 S";

How do I imitate the Microsoft version of __FUNCTION__ using gcc?

When I use the __FUNCTION__ macro/variable to print out debugging information, there seems to be a difference in what it outputs when using the Microsoft C++ compiler and gcc. For example, using the following trivial code:
class Foo
{
public:
void Bar(int a, int b, int c)
{
printf ("__FUNCTION__ = %s\n", __FUNCTION__);
}
};
int main (void)
{
Foo MyFoo;
MyFoo.Bar();
return 0;
}
Using the Microsoft Visual C++ compiler, I get
__FUNCTION__ = Foo::Bar
whereas when compiling using gcc (in this case on the Mac), I get
__FUNCTION__ = Bar
The second example is not ideal because I quite often have several classes with, say, Init() and Uninit() methods and in a debug output trace its virtually impossible to tell which one of these has been called as the class name will be missing. Now, I know you can use the __PRETTY_FUNCTION__ in place of __FUNCTION__ to get something like
__PRETTY_FUNCTION__ = void Foo::Bar(int, int, int)
Which is fine, but its a bit too verbose for what I need and gets a bit long for functions with a lot of parameters.
So my question is (at last), is there any way to get the output to look like simply Foo::Bar using gcc, as in the example above?
If you are using it for tracing, you can always use typeid(T).name() and just conditionally compile per platform. Certainly not as convenient as the macro, but it could work.
Vaguely similar to __CLASS__ macro in C++
The function-name sanctioned by the standard is defined as follows:
static const char __func__[] = "function-name ";
Example:
#include <iostream>
namespace meh {
void foobar() { std::cout << __func__ << std::endl; }
};
struct Frob {
void foobar() { std::cout << __func__ << std::endl; }
static void barfoo() { std::cout << __func__ << std::endl; }
};
int main () {
std::cout << __func__ << std::endl;
meh::foobar();
Frob().foobar();
Frob::barfoo();
}
However, output with g++:
main
foobar
foobar
barfoo
However, that is valid C++ behaviour:
ยง 8.4.1, 8: The function-local predefined variable __func__ is defined as if a definition of the form static const char __func__[] = "function-name ";
had been provided, where function-name is an implementation-defined string. It is unspecified whether such a variable has an address distinct from that of any other object in the program
I.e., you may not trust in its value. If you want to use non-portable extensions, have a look at a similar question: What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__? .

Call main() itself in c++?

#include <iostream>
#include <cstdlib>
int main() {
cout << "!!!Hello World!!!" << endl;
system("pause");
return main();
}
The above works, but it hardcoded the main() function. Is there a magic variable or macro to get the current running function?
Is it allowed in "C++"? No.
In practice, can you call main()? Yes.
Whatever the C++ Standard says, that doesn't stop the Linux g++ compiler from compiling code with main() in main().
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int y = rand() % 10; // returns 3, then 6, then 7
cout << "y = " << y << endl;
return (y == 7) ? 0 : main();
}
Which lets us do:
> g++ g.cpp; ./a.out
y = 3
y = 6
y = 7
Looking in to the assembly, we see that main is called just like any other function would be:
main:
...
cmpl $7, -12(%rbp)
je .L7
call main
...
.L7:
...
leave
ret
Not that this behavior is guaranteed, but it looks like g++ doesn't seem to really care about the standard, apart from this sarcastic warning with -pedantic
g.cpp:8: error: ISO C++ forbids taking address of function '::main'
The C++ Standard says that you may not call main() from your own code. As for getting the name of the current function, you could use the __FUNCTION__ macro, but once again this is not standard:
#include <iostream>
using namespace std;
void foo() {
cout << __FUNCTION__ << endl;
}
int main() {
foo();
}
should print "foo" or something similar if __FUNCTION__ is supported.
If a specific implementation allows this, it is not behaving correctly(a). The standard state quite explicitly in C++14, 3.6.1 Main function /3:
The function main shall not be used within a program.
(a) Keep in mind that many implementations follow some parts of the standard loosely, preferring power over strictness. That can have the unfortunate side effect that your code may not be portable to other compilers or even other versions of the same compiler.
Many implementations will also allow you to take the stricter view, such as using g++ -std=c++11 -Werror=pedantic which catches the particular issue bought up in this question, as well as quite a few others. It is that "mode" of translation that allows implementations to claim to be compliant with the standard, as per 1.4 Implementation compliance:
If a program contains a violation of any diagnosable rule ..., a conforming implementation shall issue at least one diagnostic message.
You'll see it's still quite possible to allow the code to compile and run in that case, since "diagnostic message" can mean a warning rather than an error.
Generally, no. For now it will be enough for you to know that the compiler needs to know the exact function you're calling at the compile time. You cannot do magic like, let's say
func = "my_function";
func();
if the called function name will change during runtime. (There are exceptions and ways around that, but you don't need that).
Don't think about that as a case of hard-coding: it is not. If you need to call the function, then you just write its name, and don't try to abstract it, or something.
Also, now would be a nice way to learn about the while loop, infinite loops and write without the function calls at all, e.g
int main()
{
while (1) {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
system("pause");
}
}

C++ templates problem

I am new to templates in c++.
i was trying some small programs.
CPP [80]> cat 000001.cpp 000001.hpp
#include <iostream>
#include <string>
#include "000001.hpp"
int main()
{
int i = 42;
std::cout << "max(7,i): " << ::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << ::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << ::max(s1,s2) << std::endl;
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
when i compile this program:
i get an error below:
CPP [78]> /opt/aCC/bin/aCC -AA 000001.cpp
Error (future) 229: "/opt/aCC/include_std/string.cc", line 164 # "Ambiguous overloaded function call; a
function match was not found that was strictly best for ALL arguments. Two functions that matched
best for some arguments (but not all) were "const unsigned long &max<unsigned long>(const unsigned
long &,const unsigned long &)" ["000001.hpp", line 2] and "const unsigned long &std::max<unsigned
long>(const unsigned long &,const unsigned long &)" ["/opt/aCC/include_std/algorithm", line 1762]."
Choosing "const unsigned long &max<unsigned long>(const unsigned long &,const unsigned long &)"
["000001.hpp", line 2] for resolving ambiguity.
_C_data = _C_getRep (max (_RW::__rw_new_capacity (0, this),
^^^
Warning: 1 future errors were detected and ignored. Add a '+p' option to detect and fix them before they become fatal errors in a future release. Behavior of this ill-formed program is not guaranteed to match that of a well-formed program
Could nybody please tell me what exactly the error is?
You are probably including <iostream.h> instead of <iostream> somewhere. The former hasn't existed for some time now, but for compatibility reasons, you compiler still accepts the include and replaces it with
#include <iostream>
using namespace std;
This causes std::max to be brought to the global namespace, thus resulting in an ambiguity. Replace <iostream.h> with <iostream> or rename your max function and the problem should disappear.
Edit: You've apparently fixed the include, but I bet you still have using namespace std; somewhere. You need to get rid of that. In fact you should never use using namespace in the global scope.
Edit: You might also have using std::max somewhere. You need to get rid of it too.
The code you've posted compiles just fine, there must be something else that is wrong inside "000001.hpp". Can you post the contents of that file too?
Edit: If you do as avakar says but the problem persists, that must be due to some problem with your compiler. There are two obvious workarounds I can think of: rename your max function to something else, or put it in a namespace:
namespace Foo
{
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
}
int main()
{
int i = 42;
std::cout << "max(7,i): " << Foo::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << Foo::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << Foo::max(s1,s2) << std::endl;
}
I don't know which compiler you are using but the second error tells you that the two following functions are clashing :
::max
std::max
It seems really weird, you may have a using namespace std; somewhere or worse, that one of your include use iostream.h as noted in the first error. Could you give more information about your compiler/toolchain and the content of your .hpp file?
It says that two definitions for
max<unsigned long>
were found. One definition is in 000001.hpp and the other is in /opt/aCC/include_std/algorithm. The compiler chose the one in 000001.hpp for now, so no error is present now. But it says that these two definitions may cause errors in the future.
I don't know if this causes the problem, but anyhow; you shouldnt use the name max for your global (or local) function as it is a part of STL.