[英]Unhandled exception at 0x78F90870 (ucrtbased.dll) in Metrics_Alpha.exe: 0xC0000005: Access violation reading location 0x00000000
[英]Unhandled exception at 0x0FC9E559 (ucrtbased.dll) in MyString.exe: 0xC0000005: Access violation writing location 0x00000000
我的字符串類中有一個問題:“ strcpy函數中的未處理異常”。 我沒有很多指針方面的經驗。 請給我您的建議。 先感謝您 !
使用的IDE:Visual Studio 2017
MyString.exe中0x0FC9E559(ucrtbased.dll)的未處理異常:0xC0000005:訪問沖突寫入位置0x00000000。
MyString.cpp:
#pragma warning(disable:4996)
#include "MyString.h"
#include "cstring"
#include <iostream>
using namespace std;
MyString::MyString()
{
length = 0;
content = NULL;
}
MyString::MyString(int length, const char* content)
{
this->length = length;
this->content = new char[this->length + 1];
strcpy(this->content, content);
}
MyString::MyString(const char* content)
{
length = strlen(content);
this->content = new char[length + 1];
strcpy(this->content, content);
}
void MyString::setLength(int length)
{
this->length = length;
}
const int MyString::getLength()
{
return length;
}
void MyString::setContent(char* content)
{
strcpy(this->content, content); // Unhandled exception !!!
}
const char* MyString::getContent()
{
return content;
}
ostream& operator << (ostream& out, const MyString& string)
{
out << "Content:\n" << string.content << "\n";
out << "Length:\n" << string.length << "\n";
return out;
}
const MyString operator+(MyString& string1, MyString& string2)
{
MyString concatString;
concatString.setLength(string1.length + string2.length);
strcat(string1.content, string2.content);
concatString.setContent(string1.content);
return concatString;
}
MyString::~MyString()
{
delete[] content;
}
MyString.h:
#include <iostream>
using namespace std;
class MyString
{
private:
int length;
char* content;
public:
friend ostream& operator << (ostream& out, const MyString& anotherString);
MyString(); // Constructor fara parametrii
MyString(int, const char*); // Constructor cu 2 parametrii
MyString(const char*); // Constructor cu 1 parametru
friend const MyString operator+(MyString&, MyString&);
// setters and getters
void setLength(int);
const int getLength();
void setContent(char*);
const char* getContent();
// destructor
~MyString();
};
Main.cpp:
#include <iostream>
#include "MyString.h"
using namespace std;
int main() {
MyString string1("---");
MyString string2("..");
cout << (string1 + string2);
system("pause");
return 1;
}
在
const MyString operator+(MyString& string1, MyString& string2)
{
MyString concatString;
concatString.setLength(string1.length + string2.length);
strcat(string1.content, string2.content);
concatString.setContent(string1.content);
return concatString;
}
concatString創建空的,setLength只設置長度不(再)分配的內容 ,讓你在strcpy的一個setContent空指針
您還需要在concatString中而不是string1中復制並concat
因此,舉例來說:
void MyString::setLength(int length)
{
if (length > this->length) {
char * b = new char[length + 1];
if (this->content != NULL) {
strcpy(b, this->content);
delete [] this->content;
}
this->content = b;
}
this->length = length;
}
const MyString operator+(const MyString& string1, const MyString& string2)
{
MyString concatString;
concatString.setLength(string1.length + string2.length);
strcpy(concatString.content, string1.content);
strcat(concatString.content, string2.content);
return concatString;
}
setContent不能僅僅做一個strcpy ,例如做得更好
void MyString::setContent(char* content)
{
if (content == NULL) {
if (this->content != NULL)
delete [] this->content;
this->content = NULL;
this->length = 0;
}
else {
setLength(strlen(content));
strcpy(this->content, content);
}
}
在完成這兩個變化,編譯和執行:
pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -g MyString.cpp Main.cpp
In file included from MyString.cpp:2:0:
MyString.h:22:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
const int getLength();
^
MyString.cpp:41:31: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
const int MyString::getLength()
^
In file included from Main.cpp:2:0:
MyString.h:22:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
const int getLength();
pi@raspberrypi:/tmp $ ./a.out
Content:
---..
Length:
5
sh: 1: pause: not found
在valgrind下
pi@raspberrypi:/tmp $ valgrind ./a.out
==6134== Memcheck, a memory error detector
==6134== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6134== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6134== Command: ./a.out
==6134==
Content:
---..
Length:
5
sh: 1: pause: not found
==6134==
==6134== HEAP SUMMARY:
==6134== in use at exit: 0 bytes in 0 blocks
==6134== total heap usage: 5 allocs, 5 frees, 21,261 bytes allocated
==6134==
==6134== All heap blocks were freed -- no leaks are possible
==6134==
==6134== For counts of detected and suppressed errors, rerun with: -v
==6134== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
要在編譯期間沒有警告,請不要返回const int,而只是返回int
最好使長度為size_t
而不是int
的getLength和的getContent可以是常量 ( int getLength() const
和const char* getContent() const
)
作為克里斯托弗的言論說operator+
返回字符串的副本,你沒有定義拷貝構造函數,也不是operator=
。 當一個類包含指向它需要去界定,並與近期C ++還舉
這段代碼有兩個問題。
首先,您需要實現3規則 ,因此還需要提供復制構造函數和賦值運算符。
然后setLength()
調整字符串的最大長度,但是它無法分配任何內容,因此您可能會創建緩沖區溢出,或者由於nullptr而使用默認構造函數的情況下使用UB。 這就是在operator+()
發生的情況。
實施3規則后,對operator +的快速修復可能是:
const MyString operator+(MyString& string1, MyString& string2)
{
MyString concatString(string1.length + string2.length, string1.content);
strcat(concatString.content, string2.content);
return concatString; // but this requires copy constructor to work
}
對於基於長度的構造函數,應確保該長度大於要復制的字符串。 因此,您可以斷言這一點,或者使用strncpy()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.