Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why dynamic_cast from reference causes a segmentation fault?

expr_t is base class, ident_t is derived from expr_t. I wrote some to_string overload to display different expr_t

#include <iostream>
#include <string>

struct expr_t {
  virtual ~expr_t() {}
};

struct ident_t : public expr_t {
  std::string name;

  ident_t(std::string name) : name(name) {}
};
std::string to_string(expr_t& v) {
  if (auto* id = dynamic_cast<ident_t*>(&v)) {
    return to_string(*id);
  }
  return "error";
}
std::string to_string(ident_t& v) {
  return v.name;
}

int main() {
  expr_t* b = new ident_t("c");
  std::cout << to_string(*b) << std::endl; // segfault
  delete b;
  return 0;
}

However, no output, and segfault occurs when debugging with GDB

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem is that at the point of the call return to_string(*id) the compiler doesn’t have a declaration for the second overload std::string to_string(ident_t& v). Thus the same first version will be recursively called eventually resulting in a seg fault.

To solve this you can either move the second overload’s definition before the first overload or forward declare the second overload before the definition of the first overload as shown below:

//moved the 2nd overload above first overload
std::string to_string(ident_t& v) {
  return v.name;
}

std::string to_string(expr_t& v) {
  if (auto* id = dynamic_cast<ident_t*>(&v)) {
    return to_string(*id); //now compiler knows about std::string to_string(ident_t& v)
  }
  return "error";
}

Demo

Method 2

//forward declaration for 2nd overload
std::string to_string(ident_t& v);

std::string to_string(expr_t& v) {
  if (auto* id = dynamic_cast<ident_t*>(&v)) {
    return to_string(*id); //now compiler knows about std::string to_string(ident_t& v)
  }
  return "error";
}
//definition for 2nd overload
std::string to_string(ident_t& v) {
  return v.name;
}

Demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading