【问题标题】:Exception thrown at 0x0F640E09 (ucrtbased.dll) in ConsoleApplication5.exe: 0xC0000005: Access violation writing location 0x014C3000?在 ConsoleApplication5.exe 中的 0x0F640E09 (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突写入位置 0x014C3000?
【发布时间】:2016-11-12 04:19:35
【问题描述】:

我刚刚编译了这段代码,它显示了这个错误:
在 ConsoleApplication5.exe 中的 0x0F640E09 (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突写入位置 0x014C3000。我真的不知道这个错误意味着什么,因为我已经使用 C++ 几个月了,我也尝试在任何其他网站上寻找帮助,但我没有找到任何帮助。

对于这段代码,我只能使用 c-string 函数和 <cstring> 库。我不能使用字符串对象或包含库。我也可以使用辅助方法/函数。

#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;

class MyString {
public:

    //default constructor
    MyString();

    MyString(char* chars);

    //copy constructor
    MyString(const MyString &);

    int length() const;

    //destructor
    ~MyString();

    //operator overloads
    char& operator[](int index);
    friend MyString operator+(const MyString& newWord, const MyString& newWord2);
    MyString& operator+=(const MyString& newWord);
    friend ostream& operator<<(ostream& newWord, const MyString& newWord2);
    friend istream& operator >> (istream& newWord, MyString& newWord2);
    friend bool operator==(const MyString& newWord, const MyString& newWord2);
    friend bool operator!=(const MyString& newWord, const MyString& newWord2);
    friend bool operator<(const MyString& newWord, const MyString& newWord2);
    friend bool operator<=(const MyString& newWord, const MyString& newWord2);
    friend bool operator>(const MyString& newWord, const MyString& newWord2);
    friend bool operator>=(const MyString& newWord, const MyString& newWord2);

private:
    char* value;
    int size;
};

//default constructor
MyString::MyString() {

    value = 0;
    size = 0;
}

//copy constructor
MyString::MyString(const MyString& newWord) {

    //perform a deep copy to copy each of the value to a new memory
    size = newWord.size;
    value = new char[size];

    for (int ii = 0; ii < size; ii++) {
        value[ii] = newWord.value[ii];
    }
}

//constructor with an argument
MyString::MyString(char* chars) {

    size = strlen(chars);
    value = new char[size];
    for (int i = 0; i < size; i++) {
        value[i] = chars[i];
    }

}

//find length
int MyString::length() const {

    return size;
}

//find the value of each index
char& MyString::operator[](int index) {

    return value[index];
}

//operator + (concatenate)
MyString operator+(const MyString& newWord, const MyString& newWord2) {

    MyString concatenated;
    concatenated = strcat(newWord.value, newWord.value);
    return concatenated;

}

//operator += (append)
MyString& MyString::operator+=(const MyString& newWord) {

    char * newMemory = value;
    value = new char[strlen(value) + newWord.length() + 1];
    strcpy(value, newMemory);
    strcat(value, newWord.value);
    if (size != 0)
    {
        delete[] newMemory;
    }
    size = strlen(value);
    return *this;
}

//ostream operator
ostream& operator<<(ostream& newWord, const MyString& newWord2) {

    newWord << newWord2.value;
    return newWord;
}


//istream operator
istream& operator >> (istream& newWord, MyString& newWord2) {

    const int MAX = 100;
    char* ptr = new char[MAX];
    newWord >> ptr;
    newWord2 = MyString(ptr);
    delete ptr;
    return newWord;
}

//all boolean operators
bool operator==(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value == newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator!=(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value != newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator<(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value < newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator<=(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value <= newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator>(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value > newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

bool operator>=(const MyString& newWord, const MyString& newWord2) {
    if (newWord.value >= newWord2.value) {
        return true;
    }
    else {
        return false;
    }
}

//destructor to release memory
MyString::~MyString() {
    delete[] value;
}

void test_copy_and_destructor(MyString S) {
    cout << "test: copy constructor and destructor calls: " << endl;
    MyString temp = S;
    cout << "temp inside function test_copy_and_destructor: " << temp << endl;
}

int main() {

    MyString st1("abc abc");
    MyString st2("9fgth");

    cout << "Copy constructor , << operator" << endl;

    MyString  st3(st1);

    cout << "st3: " << st3 << endl;

    test_copy_and_destructor(st2);

    MyString  st4;

    cout << "operator + " << endl;

    st4 = st3 + st2;

    cout << "st4: " << st4 << endl;

    cout << "st1 + st2: " << (st1 + st2) << endl;

    cout << "operators  [ ] " << endl;

    for (int i = 0; i < st2.length(); i++)
        cout << st2[i] << " ";

    cout << endl;

    cout << "operators  += , ==, != " << endl;

    st2 += st1;

    if (st3 == st1)
        cout << "st3 and st1 are identical " << endl;
    else cout << "st3 and st1 are not identical " << endl;

    if (st2 != st1)
        cout << "st2 and st1 are not identical " << endl;
    else cout << "st2 and st1 are identical " << endl;

    cout << "operators  < , <=, >, >= " << endl;

    if (st2 < st1)
        cout << "st2 < st1 " << endl;
    else cout << "st2 is not less than st1 " << endl;

    if (st1 <= st2)
        cout << "st1 <= st2 " << endl;
    else cout << "st1 is not less than or equal to st2 " << endl;

    if (st1 > st2)
        cout << "st1 > st2 " << endl;
    else cout << "not (st1 >  st2) " << endl;

    if (st1 >= st2)
        cout << "st1 >= st2 " << endl;
    else cout << "not (st1 >=  st2) " << endl;

    cout << "operator >> " << endl;

    //Open the data file
    ifstream input("A9_input.txt");
    if (input.fail()) {
        cout << "unable to open input file A9_input.txt, Exiting..... ";
        system("pause");
        return 0;
    }
    MyString temp1;
    MyString temp2("aaa");
    input >> temp1;
    input >> temp2;
    cout << "first element of input file: " << temp1 << endl;
    cout << "second element of input file: " << temp2 << endl;
    input.close();

    cout << "MyString says farewell....." << endl;
    system("pause");
    return 0;
}

【问题讨论】:

  • strlen(chars) 的长度不足以容纳整个 c 字符串。
  • 此代码优于it was when you last asked about it。您仍在比较指针而不是值,并且您的 operator+ 仍然滥用 strcat。
  • 您的MyString 赋值运算符(operator=)在哪里?您的main 程序没有进行彻底的测试,因为它不会在任何地方测试temp1 = temp2;
  • 另外,你只需要写operator &lt;operator==完整的实现。所有其他比较运算符都可以根据这两个运算符编写——无需从头开始编写其他运算符。例如operator != 就是return !(newWord == newWord2);
  • 让我们回到基础。您不允许使用 C++ 字符串,但您可以使用现有的所有其他 C++ 功能吗?这是为什么呢?

标签: c++ arrays pointers dynamic-memory-allocation c-strings


【解决方案1】:

您的错误很可能出现在以下代码上:

st4 = st3 + st2; # note that you initialize st4 with type MyString but inside operator+ you assign a char[] to MyString. Just letting you know since you dont have a operator= overloaded function 

来电:

MyString operator+(const MyString& newWord, const MyString& newWord2) {

    MyString concatenated;
    concatenated = strcat(newWord.value, newWord.value); # you have an mistake here, second parameter should be newWord2.value
    return concatenated;

}

您假设您的 newWord.value 拥有足够的空间来容纳 newWord.value 和 newWord2.value。但不是您在构造函数中将其初始化为 newWord.value ,因此您基本上是在写入违反内存访问的区域。您要做的是使 newWord 足够大以容纳两个字符串。

对 strcat 的引用:http://www.cplusplus.com/reference/cstring/strcat/

【讨论】:

  • 不,他绝对不应该让const newWord 大到足以容纳两个字符串(并在其中连接),因为修改 newWord 确实是错误的做法。他需要使concatenated 字符串足够大以容纳结果,然后将两个字符串都放入其中。执行此操作的模式通常是“MyString concatenated(newWord); return concatenated += newWord2;”(因为无论如何都定义了operator +=,虽然不是很干净)。
【解决方案2】:

您的operator + 正在写入超过分配的内存(缓冲区溢出)。您可以轻松地将其更改为非常简单的:

MyString operator +(const MyString& newWord, const MyString& newWord2) {
    MyString concatenated;
    return concatenated += newWord2;
}

那么它甚至不需要是类的friend

operator += 也是错误的,因为你的字符串不是最初创建的 NULL 终止的,所以事实上你根本不应该使用 strlen()strcpy()strcat(),因为你在连接任意一起使用内存(读取过去分配的内存也可能出现段错误)。因此,您应该考虑是否希望字符串 NULL 终止(并按原样使用)。

无论如何,operator += 的定义也不是很有效,例如更干净有效的定义可能是:

MyString& MyString::operator+=(const MyString& newWord) {
    size_t newSize = size + newWord.size;
    char * newValue = new char[newSize /* + 1 */]; // not null terminated, but cannot be printed easily then
                                          // or make the string initially null terminated and then allocate +1 and null terminate then
    memcpy(newValue, value, size);
    memcpy(newValue + size, newWord.value, newWord.size /* + 1 */);
    delete[] value;
    value = newValue;
    size = newSize;
    return *this;
}

看到了吗?不使用遍历字符串的strlen()(在您的情况下不是以null结尾),因为无论如何您都知道字符串的大小。您还可以在构造函数中使用memcpy(),而不是for (int i = 0; i &lt; size; i++) 循环。或者 strcpy() 并使字符串以空值结尾(但即使这样,memcpy() 也可以使用,因为它更快 - 不会在复制的每个字符上测试 '\0')。

运算符==!= 似乎也不太正确,因为只比较了指针(因此字符串只会与自身相等,但不会与存储在@987654339 中的具有相同字符的其他字符串相等@)。

此外,由于初始字符串不是以 null 结尾的,operator &lt;&lt; 也将无法正常工作(将打印出字符串之后的任意内存)。一般来说,我建议将字符串 value 始终以 null 结尾以避免一些问题。

最后,你肯定需要定义operator =,因为现在你使用的是默认的浅拷贝,所以使用这段代码你将在销毁st4(以及任何其他分配有= 的字符串)。请注意,正确实现 operator = 也很棘手 - 请注意自分配情况。

【讨论】:

  • 如果类有一个工作拷贝构造函数和析构函数,那么实现operator = 并不难。事实上,它非常简单。只需创建一个临时副本,将临时副本内部替换为当前内部,然后返回。基本上是4行功能。 See this
【解决方案3】:

您的代码还有其他问题,大部分与比较运算符有关。

MyStringoperator &lt;operator== 不正确。要比较 c 风格的字符串,请使用 strcmp,而不是 ==。相反,您的比较运算符是比较指针值,而不是指向的数据。


第二个问题是您需要做的就是完全实现operator &lt;operator ==,因为所有其他比较运算符都可以根据这些函数实现。

把这些放在一起,你的类的实现应该是这样的:

#include <cstring>
//...     
class MyString {
public:
    //...    
    friend bool operator==(const MyString& newWord, const MyString& newWord2);
    friend bool operator!=(const MyString& newWord, const MyString& newWord2);
    friend bool operator<(const MyString& newWord, const MyString& newWord2);
    friend bool operator<=(const MyString& newWord, const MyString& newWord2);
    friend bool operator>(const MyString& newWord, const MyString& newWord2);
    friend bool operator>=(const MyString& newWord, const MyString& newWord2);

private:
    char* value;
    int size;
};

bool operator==(const MyString& newWord, const MyString& newWord2) 
{ return strcmp(newWord.value, newWord2.value) == 0; } 

bool operator<(const MyString& newWord, const MyString& newWord2) 
{ return strcmp(newWord.value, newWord2.value) == -1; }

bool operator!=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord == newWord2); }

bool operator<=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord2 < newWord); }   

bool operator> (const MyString& newWord, const MyString& newWord2)
{ return newWord2 < newWord; }

bool operator>=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord < newWord2); }

请注意,运算符使用&lt;== 来实现其他运算符。


第三个问题是你缺少一个赋值运算符

MyString& operator=(const MyString&)

没有这个函数,你不能在不破坏内存的情况下将MyString 对象相互分配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 2018-06-26
    • 2021-07-31
    • 1970-01-01
    相关资源
    最近更新 更多