munmap_chunk(): invalid pointer: 0x00007fffbef49d90 in a recursive function - c++

I am new to programming, so even after trying to google this error I couldn't find anything that was either relevant to my project or was simple enough for me to follow.
I have to make a function that reverses a string iteratively, then another function which does so recursively. The iterative function works perfectly fine:
string reverse(string str_input) {
string result = ""; //initialize a blank string to hold reversed string
for(int i = (str_input.length() - 1); i >= 0; i--) {
result += str_input.substr(i,1); //concatenates the string backwards
}
return result;
However when I tried to make it recursive, I got an invalid pointer error. I've copied my main I'm using for testing and the other function here:
string reverse_rec(string str_input, string result, int input_length);
int main() {
string str_input = "hello";
int input_length = (str_input.length() - 1);
string result = "";
cout<< reverse_rec(str_input, result, input_length) << endl;
return 0;
}
string reverse_rec(string str_input, string result, int input_length) {
if(input_length <= 0) {
return result;
} else {
reverse_rec(str_input, result += str_input.substr(input_length,1), --input_length);
}
}
Does anyone have any hints as to what might be causing this error? From what I've read, most of the people got this error when trying to delete things, but I don't seem to be deleting anything in this program...
Note: We have to do this by concatenating substrings and not by using arrays, as we haven't covered arrays in depth yet.

You forgot to return:
reverse_rec(str_input, result += str_input.substr(input_length,1), --input_length);
^^^^^
Such errors can be easily spotted by the compiler. You should enable warnings.

Related

Initialising a vector with anoter vector, returned from a function

I'm attempting to create a vector called mems which is declared using the returned vector from my myMembers() function. For some reason when I use the line:
vector<string> mems = myMembers(); It returns an error:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
This error doesn't appear at compilation, but instead it appears once the program reaches this line of code. I've been researching for a few hours on what to do to fix it, but I'm really not sure.
The code that I've written so far is as follows:
vector<string> Person::myMembers(){
fstream file;
file.open("myFile.txt");
string myLine;
vector<string> mems;
while(getline(myFile, myLine)){
vector<string> myLine = split(myLine, ',');
mems.push_back(myLine.at(0));
for (int i = 5; i < myLine.size(); i++){
mems.push_back(myLine.at(i));
}
}
return mems;
}
The above function will get the name at index 0, and the list of names from index 5 to n. It will then place these names into a vector called mems, and return it.
(I should make you aware that split is a function I've written which will simply split a line by a specified delimiter, and then put it into a vector).
Then, later in my code, I create a new vector, called mems, and set it equal to the output of myMembers()
vector<string> mems = myMembers()
I know that it's the above line of code that's causing the error, but I don't know why, or how to fix it.
Any help would be greatly appreciated.
Thanks for your time :)
Edit
Upon mention that the error might be a part of the splitString, please find the code for my SplitString function below:
vector<string> split(string myString, char delimiter){
string temp = 0;
vector<string> splitString;
for (int i = 0; i < myString.size(); i++){
if (myString[i] != delimiter){
temp += myString[i];
} else {
splitString.push_back(temp);
}
}
return splitString;
}
I've discovered the issue for the program. The split() function was causing the error, because temp was initialised as string temp = 0; which meant it was trying to initialise a string with an integer value.
The correct code for the split() function is as follows:
ector<string> split(string myString, char delimiter){
string temp = "";
vector<string> splitString;
for (int i = 0; i < myString.size(); i++){
string temp = "";
if (myString[i] != delimiter){
temp += myString[i];
} else {
splitString.push_back(temp);
}
}
return splitString;
}
This then lets the split() function return a non-null string, and allows the program to run as it should.

Passing the char *str inside the function

I newly started C++ and it feels pretty wired while writing Java for a while. So, I have this array,
char values[][10] = {"miami", "seattle", "berlin"};
int rows = sizeof values / sizeof values[0];
This is this is the function where I would like to pass the value,
// a function to reverse the strings
void App::reverse(char *str) {
}
When I do the loop, I can't apparently pass the value there,
for (int i = 0; i < rows; ++i) {
// first character of the string
char *firstPtr = values[i];
reverse(firstPtr);
}
The line reverse(firstPtr) provides error which I don't understand. The error message says Too few arguments, expected 2.
What is the issue here? I apologize for any mistakes as writing the C++ for the first time and the pointer stuff feels strange.
UPDATE
This is the piece of code I would like to exexute,
void App::reverse(char* str) {
// get the first character of the string
char *ptrEnd = str;
char temp;
if (str){
while (*ptrEnd) {
ptrEnd++;
}
ptrEnd--;
// as long the first adddress is lesser than the end
while (str < ptrEnd) {
temp = *str;
*str++ = *ptrEnd;
*ptrEnd-- = temp;
}
}
}
There is too little information here to be sure, but it looks like you have
using namespace std;
Somewhere in your code. Don't do this! In this case, the standard library has a function reverse() in std that takes two parameters.
Furthermore, you have void App::reverse(char *str), but that cannot be seen from void myArray::reverse(char* str), so your own reverse() cannot be called as-is - you would need to do App::reverse() if the function is a class static.

Weird behaviour of the code

I saw that a part of my code did not work as expected. It does not go into the if statement and give an error while it should. I tried to examine the code and found something very odd. When I add cout << i in the for loop to check, it starts to work well. Can anyone explain what is the problem with it? Note: airports is a vector of Airport objects. Airport::getName() returns its name as string.
string name = "smth";
//this is the loop with unexpected behaviour
for (int i = 0; i < airports.size(); i++)
{
//when the following line is taken outside the comment, it works well:
//cout << i;
if (isEqualNoCaseSense(name, airports[i].getName()))
{
cout << "Could not create airport " << name << ". It already exists." << endl;
return;
}
}
The function I used to compare strings without case sensitivity:
bool isEqualNoCaseSense(string str1, string str2)
{
if (str1.size() != str2.size())
return false;
char *lowerStr1 = new char[str1.size()];
char *lowerStr2 = new char[str2.size()];
for (int i = 0; i < str1.size(); i++)
{
lowerStr1[i] = tolower(str1[i]);
lowerStr2[i] = tolower(str2[i]);
}
if (strcmp(lowerStr1, lowerStr2) == 0)
{
delete[] lowerStr1;
delete[] lowerStr2;
return true;
}
else
{
delete[] lowerStr1;
delete[] lowerStr2;
return false;
}
}
EDIT: Correcting the compare function fixes it, but I still wonder why cout << i fixed it
The problem is that you haven't terminated your strings, but if you just write a sensible function it will work correctly:
bool isEqualNoCaseSense(const string& str1, const string& str2)
{
if (str1.size() != str2.size())
return false;
for (int i = 0; i < str1.size(); ++i)
if (tolower((unsigned char)str1[i]) != tolower((unsigned char)str2[i]))
return false;
return true;
}
No unnecessary allocation, and only loops through the strings up to the first mismatch.
EDIT: Correcting the compare function fixes it, but I still wonder why cout << i fixed it
Because the program had undefined behaviour, so anything can happen. Adding random, unrelated code might change the memory allocation patterns of the code, or cause the compiler to optimise it slightly differently. You'll go mad trying to reason about some kinds of undefined behaviour. Just avoid it.
strcmp expects NULL terminated strings. So you needed to reserve one more character for the lowerStr1, lowerStr2 arrays and set the last character of each array to NULL. Failing to do so, created undefined bahaviour to your program.
But you could bypass all these issues if you use strncmp function passing str1.size() as the third argument, since you already check if the two strings have equal size:
if (strncmp(lowerStr1, lowerStr2, str1.size()) == 0)

C++ char sequence function always return empty string

Just start learning C++ and trying to make a simple function that do substring with following code:
char* substring(int start, int end, const char* target)
{
size_t length = strlen(target);
char result[(length + 1)];
int iterator = 0;
for(int i = start; i < length; i++)
{
if(i <= end)
{
result[iterator] = target[i];
iterator++;
}
}
result[iterator] = '\0';
cout << result << endl; // This give correct result "aya";
return result;
}
When I use these function on main method:
int main(int argc, char** argv) {
char some_text[] = "Saya Makan";
char* sub = substring(1, 3, some_text); // No string returned
cout << "Substring Result is: " << sub;
return 0;
}
It give output is like this:
aya
Substring Result is:
RUN SUCCESSFUL (total time: 44ms)
As seen on the result, my function isn't returning anything but empty string although a line of code before return, the "result" variable echoed result correctly. Would you please explain to me what is happening inside my function, am I missing something?
You are returning pointer to a local array which is not required to live beyond the function.
You need to make the buffer persist beyond the scope of the function by allocating it dynamically using malloc. And ofcourse remember to free it later.
Oh just noticed its C++.
So drop the idea of malloc and free simply use std::string and not char *.

Basic C++: convert from char to string

I'm a little confused by the class code. Here's what I'm trying to do:
//Program takes "string text" and compares it to "string remove". Any letters in
//common between the two get deleted and the remaining string gets returned.
#include <string>
#include "genlib.h"
string CensorString1(string text, string remove);
int main() {
CensorString1("abcdef", "abc");
return 0;
}
string CensorString1(string text, string remove) {
for (int i = 0; text[i]; i++){
for (int n = 0; remove[n]; n++){
if (i != n){
string outputString = ' '; //to store non repeated chars in,
//forming my return string
outputString += i;
}
}
}
return outputString;
}
I'm getting an error on the "outputString += 1" saying: "cannot convert from "char" to
std::basic_string
I'm also getting an error on the "return outputString" saying: undeclared identifier
???????
I get that I'm putting a "char" on a "string" variable but what if shortly that "char" will soon be a string? Is there a way to pass this?
I'm always forgetting libraries. Can someone recommend a couple of standard/basic libraries I should always think about? Right now I'm thinking , "genlib.h" (from class).
C++ is kicking my ass. I can't get around constant little errors. Tell me it's going to get better.
There are many errors in your code:
Your outputString needs to be in the outer scope (syntax)
You compare i to n instead of text[i] to remove[n] (semantic)
You are adding i to the output instead of text[i] (semantic)
You ignore the return of CensorString1 (semantic)
Here is your modified code:
string CensorString1(string text, string remove) {
string outputString;
for (int i = 0; text[i] ; i++){
for (int n = 0; remove[n] ; n++){
if (text[i] != remove[n]){
outputString += text[i];
}
}
}
return outputString;
}
This has some remaining issues. For example, using text[i] and remove[n] for termination conditions. It is also very inefficient, but it should be a decent start.
At any rate, strings are always double-quoted in C and C++. Single-quoted constants are char constants. Fix that and you should probably be all right.
Also, look at this SO question: How do you append an int to a string in C++?
Good luck at Stanford!
There are some problems there:
string outputString = ' '; will try to construct a string from a char, which you can't do. You can assign a char to a string though, so this should be valid:
string outputString;
outputString = ' ';
Then, outputString is only visible within your if, so it won't act as an accumulator but rather be created and destroyed.
You're also trying to add character indices to the string, instead of characters, which is not what I think you want to be doing. It seems like you're mixing up C and C++.
For example, if you want to print the characters of a string, you could do something like:
string s("Test");
for (int i=0;i<s.length();i++)
cout << s[i];
Finally, I'd say that if you want to remove characters in text that also appear in remove, you'd need to make sure that none of the characters in remove match your current character, before you add it to the output string.
This is an implementation of what I think you want, your code has multiple problems which just showed up described in multiple other answers.
std::string CensorString1(std::string text, std::string remove) {
std::string result;
for (int i = 0; i<text.length(); i++) {
const char ch = text[i];
if(remove.find(ch) == -1)
result.append(1,ch);
}
return result;
}