Terminate Called After Throwing an Instance of 'Std::Logic_Error' What(): Basic_String::_M_Construct Null Not Valid

How to fix 'std::logic_error' what(): basic_string::_M_construct null not valid error?

The problem is the two return 0; statements in your function. The function returns a std::string, which has no constructors that accept an int as input. But, it does have a constructor that accepts a const char * pointer, which 0 is implicitly convertible to. However, constructing a std::string with a null char * pointer is undefined behavior, and your implementation has chosen to throw a std::logic_error exception that you are not catching in your code.

In this case, I would simply return a blank string instead:

std::string myfunc(const std::string &input){
if (input.empty()) return "";
for (int i = 0; i < input.size(); ++i){
char ch = input[i];
if ( !((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) ) return "";
}
return input;
}

The caller can then check if the return value is empty, if it wants to:

if (myfunc(input).empty())
// error, do something
else
// OK, do something else

Which would be better served with a function that returns a bool instead of a std::string:

bool isvalid(const std::string &input){
if (input.empty()) return false;
for (int i = 0; i < input.size(); ++i){
char ch = input[i];
if ( !((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) ) return false;
}
return true;
}

// if you still needed this function for something...
std::string myfunc(const std::string &input){
if (!isvalid(input)) return "";
return input;
}

if (!isvalid(input))
// error, do something
else
// OK, do something else

Why does it show terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_S_construct null not valid

In short: You are trying to initialize your arrays with 0, which is a nullptr. So you are actually trying to initialize your first string in the array with a nullptr.

Let's examine

string patient_name[NUM_PATIENTS] = { 0 };
  • It defines an old style C array of NUM_PATIENT strings.
  • It initializes this array with { 0 }.
  • ... which means, the first string get's initalized with 0, the rest of the strings get default-initialized.
  • ... which means, the first string in the array is initialized thus: string(0), which is similar to string(nullptr) - which probably leads to your exception string::_S_construct null not valid

Actually all your attempts at initalizing are wrong.

You don't need to write = {0} for the patient_name[NUM_PATIENT] array at all, because the strings in this array are "default-initialized". They know how initialize themselves to an empty string.
string patient_name[NUM_PATIENT]; is enough.

But your other arrays don't get properly initialized at all. = {0} will initialize the first element of your vector. The remaining elements are "default" initialized (for classes) or not initialized at all (for doubles).

Don't use patient_name[NUM_PATIENT] at all. Get a better textbook. This is an old-style C array. Use std::vector (best) or std::array (better).

Much better would be this:

   std::vector<string> patient_names;
std::vector<double> medication...

for (size_t i=0; i<NUM_PATIENT; ++i) {
string next_patient;
getline(patients, next_patient);
patient_names.emplace_back(next_patient);
...

or, to stick close to the text book:

   std::vector<string> patient_name(NUM_PATIENTS);
...
while (count<NUM_PATIENTS) {
getline(patients, patient_name[count]);

How to fix terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_M_construct null not valid exception?

You're trying to initialize an std::string with 0. std::string doesn't have a ctor that takes just an int, but it does have one that takes a pointer, and an integer literal 0 can convert implicitly to a pointer--specifically, a null pointer.

But, when you pass a pointer to initialize an std::string, it's required to be a non-null pointer, so passing zero breaks things (and the error message you're getting is telling you that you've tried to break it).

My advice would be to get rid of your: DEFAULT_NODE_VALUE, and instead provide a default argument to value initialize the item in the node:

node(T a = T()):val(a){}

In which case, it'll work about as it previously did for things like node<int>, but will also work correctly for types that can't be initialized from 0. This also gets rid of the ugly DEFAULT_NODE_VALUE in the client code.

how to fix terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_M_construct null not valid

TL;DR:

Change

std::string i = 0;

and friends to

std::string i;

This will produce empty strings. While you are at it, consider giving the string a meaningful identifier like input or yes_no. This will likely help a lot when debugging later and descriptive code greatly reduces the need for comments.

The problem:

std::string i = 0;

and friends.

Why it is a problem:

This is an initialization so a constructor is called.

std::string doesn't have a constructor that can convert an integer, but it does have a constructor that will take a pointer to a character array and unfortunately an integer literal of 0 looks enough like the old definition of a NULL pointer

#define NULL 0

to call it rather than emit a compiler error.

Constructing a std::string with a NULL pointer is pretty much instantly fatal, so the string constructor traps it and throws an exception.

std::string i = 1;

does not have this problem. The compiler instantly rejects it because there is no historical equivalency between 1 and a pointer or anything else that can be used to initialize a string.

Side note:

Later in the code watch out for checkforwinner (int*gameBoard). It looks like the return type is missing. You'll need to fix this because the program is not running as expected.

There could be a compiler warning for that. If there is, don't ignore warnings. They are the first line of defense against logic errors, so if anything you want to see MORE warnings so that you can fix them before they become harder-to-diagnose runtime problems. Check your compiler documentation for how to turn up the warning level and then crank it up LOUD!

Why does the below code give 'std::logic_error' what(): basic_string::_M_construct null not valid?

The problem is caused by

return true;

in sort_string. It needs to be

return false;

When you reach that line, xy is equal to yx. Hence yx < xy is false, not true.

The line

return xy >= yx;

works because that line is the same as

return yx < xy;


Related Topics



Leave a reply



Submit