Oct 28, 2020 at 11:57am UTC
if I run this like
I get:
St13runtime_error
too few arguments
if I run this like:
I get:
std::runtime_error
too few arguments
How can demangle names within my program.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include<iostream>
#include<vector>
#include<typeinfo>
#include<stdexcept>
int main(int argc, char ** argv) try {
std::vector<const char *> args(argv, argv + argc);
const char * dir = args[1];
const char * regex = args[2];
if (args.size() !=3) throw std::runtime_error("too few arguments" );
return 0;
}
catch (std::exception& e) {
std::cout << typeid (e).name() << '\n' ;
std::cout << e.what() << '\n' ;
}
Last edited on Oct 28, 2020 at 12:11pm UTC
Oct 28, 2020 at 12:19pm UTC
Sorry maybe I wasn't clear, I want it to throw an exception. The pipe is so the program c++filt can demangle the name. What I want is too demangle the name before I send it to the terminal.
Last edited on Oct 28, 2020 at 12:23pm UTC
Oct 28, 2020 at 1:30pm UTC
You're saying you want to implement the logic that c++filt does within your program itself?
Each compiler will have its own way of doing name demangling.
Are you on a Linux platform using gcc or clang? If you install the binutils-dev package, apparently you can link to a library that do the same demangling.
https://stackoverflow.com/a/4779961 On Linux you can use /usr/include/demangle.h which comes with binutils-dev package. You'll have to link to the libiberty from binutils.
Then, it looks like you can pass the mangled string into a demangle() function.
Edit:
According to
https://en.wikipedia.org/wiki/Name_mangling
another alternative is to use the builtin GCC ABI:
1 2 3 4 5 6 7 8 9 10 11 12
#include <stdio.h>
#include <stdlib.h>
#include <cxxabi.h>
int main() {
const char *mangled_name = "_ZNK3MapI10StringName3RefI8GDScriptE10ComparatorIS0_E16DefaultAllocatorE3hasERKS0_" ;
int status = -1;
char *demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, &status);
printf("Demangled: %s\n" , demangled_name);
free(demangled_name);
return 0;
}
Last edited on Oct 28, 2020 at 1:41pm UTC
Oct 28, 2020 at 1:54pm UTC
This works but I was hoping for something better.
Edit this was posted before I saw the above reply
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#include<iostream>
#include<vector>
#include<cstdio>
#include<memory>
#include<typeinfo>
#include<stdexcept>
#include<string>
#include<array>
std::string exec(const std::string cmd) {
std::array<char , 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype (&pclose)> pipe(popen(cmd.c_str(), "r" ), pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!" );
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr ) {
result += buffer.data();
}
return result;
}
std::string demangle(const std::string mangled){
return exec(std::string("c++filt -t " ) + mangled);
}
int main(int argc, char ** argv) try {
std::vector<const char *> args(argv, argv + argc);
throw std::runtime_error("too few arguments" );
return 0;
}
catch (std::exception& e) {
std::cout << demangle(typeid (e).name()) << '\n' ;
std::cout << e.what() << '\n' ;
}
Last edited on Oct 28, 2020 at 2:00pm UTC
Oct 28, 2020 at 2:02pm UTC
@Ganado Thank you very much -- it is exactly what I was looking for.
Last edited on Oct 28, 2020 at 2:03pm UTC