I have been learning c++ recently, and for some practice in the language I decided to make and implementation of a sting similar to that of Java in c++. Everything was going smoothly until my split(vector<String> &dest, char delim)
function was causing my program to crash. I found that the error was caused by adding a String to the vector, and I could reproduce the error like so:
const String s("abcdefg");
dest.push_back(s);
I'm also particularly concerned about this error because it causes my computer to make a grinding sound until the program crashes.
Note that every other method in the String class works as far as I have tested, this question is only about why my program crashes when adding to the vector.
The String class implementation (although I think most of the code is not needed):
#include <string.h>
#include <iostream>
#include <vector>
#include "jstring.h"
using namespace std;
CharArray::CharArray() {
length = 0;
_value = new char[0];
}
CharArray::CharArray(int len) {
length = len;
_value = new char[len];
}
CharArray::CharArray(char* value, int len) {
length = len;
_value = new char[len];
for(int i = 0;i < len;++ i) {
_value[i] = value[i];
}
}
CharArray::CharArray(const char* value, int len) {
length = len;
_value = new char[len];
for(int i = 0;i < len;++ i) {
_value[i] = value[i];
}
}
CharArray::~CharArray() {
delete[] _value;
}
char* CharArray::native_value() {
return _value;
}
char& CharArray::operator[](const int index) {
if(check_index(index)) {
return _value[index];
}
return _value[0];
}
inline bool CharArray::check_index(int i) {
return i > 0 && i < length;
}
String::String() {
__str = new CharArray();
}
String::String(const char* str) {
__str = new CharArray(str, strlen(str));
}
String::String(char* str) {
__str = new CharArray(str, strlen(str));
}
String::String(std::string str) {
__str = new CharArray(str.c_str(), str.size());
}
inline void String::dltval() {
delete __str;
__str = 0;
}
String::~String() {
dltval();
}
int String::length() {
return __str->length;
}
bool String::empty() {
return __str->length == 0;
}
void String::get_chars(int srcpos, char* dest, int destpos, int len) {
if(len > __str->length)
return;
int dpo = 0;
for(int i = srcpos;i < len;++ i, ++ dpo) {
dest[destpos + dpo] = (*__str)[i];
}
}
void String::get_all_chars(int srcpos, char* dest, int destpos) {
get_chars(srcpos, dest, destpos, __str->length);
}
bool String::equals(const char* str) {
if(__str->length != strlen(str))
return false;
for(int i = 0;i < strlen(str);++ i) {
if((*__str)[i] != str[i])
return false;
}
return true;
}
bool String::equals_ignore_case(const char* str) {
if(__str->length != strlen(str))
return false;
for(int i = 0;i < strlen(str);++ i) {
char c1 = str[i], c2 = (*__str)[i];
if(c1 >= 97 && c1 <= 122 || c2 >= 97 && c2 <= 122) {
if(c1 >= 97 && c1 <= 122)
c1 = (char)(((int)c1) - 32);
if(c2 >= 97 && c1 <= 122)
c2 = (char)(((int)c2) - 32);
if(c1 != c2)
return false;
}else{
if(c1 != c2)
return false;
}
}
return true;
}
bool String::starts_with(const char* str) {
if(strlen(str) > __str->length)
return false;
if(strlen(str) == __str->length)
return equals(str);
for(int i = 0;i < strlen(str);++ i) {
if(str[i] != (*__str)[i])
return false;
}
return true;
}
bool String::ends_with(const char* str) {
if(strlen(str) > __str->length)
return false;
if(strlen(str) == __str->length)
return equals(str);
for(int i = __str->length - strlen(str), j = 0;i < __str->length;++ i, ++ j) {
if(str[j] != (*__str)[i])
return false;
}
return true;
}
int String::index_of(char c) {
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] == c)
return i;
}
return -1;
}
int String::index_of(const char* str) {
if(strlen(str) == 0)
return -1;
int j = 0, k = 0;
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] != str[j]) {
j = 0;
continue;
}else{
if(j == 0)
k = i;
}
++ j;
if(j == strlen(str))
return k;
}
return -1;
}
int String::last_index_of(char c) {
int j = -1;
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] == c)
j = i;
}
return j;
}
int String::last_index_of(const char* str) {
if(strlen(str) == 0)
return -1;
int j = 0, k = 0, l = -1;
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] != str[j]) {
j = 0;
continue;
}else{
if(j == 0)
k = i;
}
++ j;
if(j == strlen(str))
l = k;
}
return l;
}
String String::substring(int begin) {
int len = __str->length - begin;
char *substr = new char[len];
for(int i = begin, j = 0;i < __str->length;++ i, ++ j) {
substr[j] = (*__str)[i];
}
String ret(substr);
delete[] substr;
return ret;
}
String String::substring(int begin, int end) {
if(end <= begin)
throw "Index out of bounds";
int len = end - begin;
char *substr = new char[len];
for(int i = begin, j = 0;i < end;++ i, ++ j) {
substr[j] = (*__str)[i];
}
String ret(substr);
delete[] substr;
return ret;
}
String String::concat(const char* str) {
int nlen = __str->length + strlen(str);
char *cc = new char[nlen];
int j = 0;
for(int i = 0;i < __str->length;++ i) {
cc[j] = (*__str)[i];
++ j;
}
for(int i = 0;i < strlen(str);++ i) {
cc[j] = str[i];
++ j;
}
String ret(cc);
delete[] cc;
return ret;
}
void String::replace(int start, const char* str, int olen) {
char *nstr = new char[__str->length + (strlen(str) - olen)];
for(int i = 0;i < start;++ i) {
nstr[i] = (*__str)[i];
}
if(strlen(str) != 0) {
for(int i = start, j = 0;i < start + strlen(str);++ i, ++ j) {
nstr[i] = str[j];
}
}
for(int i = start + olen, j = start + strlen(str);i < __str->length;++ i, ++ j) {
nstr[j] = (*__str)[i];
}
int osize = __str->length;
dltval();
__str = new CharArray(nstr, osize + (strlen(str) - olen));
delete[] nstr;
}
String& String::replace(char ch, char newChar) {
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] == ch)
(*__str)[i] = newChar;
}
return *this;
}
String& String::replace_all(const char* str, const char* nstr) {
String _nstr(__str->native_value());
int j = 0, k = 0, c = 0;
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] == str[j] && j == 0) {
k = i;
}else if((*__str)[i] != str[j] && j != 0 && (*__str)[i] == str[0]) {
k = i;
j = 0;
}else if((*__str)[i] != str[j]) {
j = 0;
continue;
}
++ j;
if(j == strlen(str)) {
_nstr.replace(k + c * (strlen(nstr) - strlen(str)), nstr, strlen(str));
++ c;
j = 0;
}
}
int olen = __str->length;
dltval();
__str = new CharArray(_nstr.c_str(), olen + c * (strlen(nstr) - strlen(str)));
return *this;
}
String& String::remove(char ch) {
char *nstr = new char[__str->length];
int j = 0;
for(int i = 0;i < __str->length;++ i) {
if((*__str)[i] != ch) {
nstr[j] = (*__str)[i];
++ j;
}
}
dltval();
__str = new CharArray(nstr, j);
delete[] nstr;
return *this;
}
String& String::remove_all(const char* str) {
replace_all(str, "");
return *this;
}
bool String::contains(const char* str) {
return index_of(str) != -1;
}
void String::split(std::vector<String> &dest, char ch) {
}
void String::split(vector<String> &dest, const char* str) {
}
String& String::to_uc() {
for(int i = 0;i < __str->length;++ i) {
int cp = ((int)(*__str)[i]);
if(cp >= 97 && cp <= 122) {
cp -= 32;
}
(*__str)[i] = ((char)cp);
}
return *this;
}
String& String::to_lc() {
for(int i = 0;i < __str->length;++ i) {
int cp = ((int)(*__str)[i]);
if(cp >= 65 && cp <= 90) {
cp += 32;
}
(*__str)[i] = ((char)cp);
}
return *this;
}
String String::trim() {
int st = 0, len = __str->length;
while((st < len) && (*__str)[st] <= 32) {
++ st;
}
while((st < len) && (*__str)[len - 1] <= 32) {
-- len;
}
return substring(st, len);
}
CharArray& String::get_chars() {
return *__str;
}
char* String::c_str() {
return __str->native_value();
}
char& String::operator[](const int index) {
return (*__str)[index];
}
ostream& operator<<(ostream &out, const String &str) {
for(int i = 0;i < str.__str->length;++ i) {
out << (*str.__str)[i];
}
return out;
}
What I used to reproduce the crash:
#include <iostream>
#include <cstdlib>
#include <vector>
#include "jstring.h"
using namespace std;
void add_to_vec(vector<String> &dest) {
const String s("abcdefg");
dest.push_back(s);
}
int main(int argc, char **argv) {
vector<String> strs;
add_to_vec(strs);
return EXIT_SUCCESS;
}