0x0037A5C2处抛出的异常project.exe: 0xC0000005: 访问冲突写入位置0xDDDDDDDD在程序末尾
Exception thrown at 0x0037A5C2 project.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD at the end of the program
我在程序的最后通过简单地创建指定 class 的实例遇到了这个运行时异常,所以我认为问题出在构造函数、复制构造函数、复制赋值运算符或析构函数。在我有限的 cpp 知识范围内,我已经阅读并遵循了三个规则。
Source.cpp
#include "Header.h"
#include <iostream>
using namespace std;
int main() {
string command = "CREATE TABLE table_name IF NOT EXISTS ((column_1_name,type,default_value), (column_2_name,type,default_value))";
string columns[20] = { "column_1_name,type,default_value", "column_1_name,type,default_value" };
string commandData[9] = { "table_name", "IF NOT EXISTS" };
CommCREATETABLE comm(command, columns, commandData, 2, 2);
}
相关代码来自Header.h
class CommCREATETABLE {
string fullCommand = "";
string* columns = nullptr;
string* commandData = nullptr;
string tableName = "";
int nrOfColumns = 0;
int nrOfElements = 0;
bool valid = false;
构造函数:
CommCREATETABLE(string command, string* columns, string* commandData, int nrOfRows, int nrOfElements) {
this->setNrOfColumns(nrOfRows);
this->setNrOfElements(nrOfElements);
this->setCommand(command);
this->setColumns(columns);
this->setCommandData(commandData);
this->valid = checkInput(this->commandData, this->columns);
this->setTableName(commandData[0]);
}
拷贝构造函数、拷贝赋值运算符、析构函数:
CommCREATETABLE(const CommCREATETABLE& comm) {
this->setNrOfColumns(comm.nrOfColumns);
this->setNrOfElements(comm.nrOfElements);
this->setCommand(comm.fullCommand);
this->setColumns(comm.columns);
this->setCommandData(comm.commandData);
this->setTableName(comm.tableName);
this->valid = comm.valid;
}
~CommCREATETABLE() {
if (this->columns != nullptr) {
delete[] this->columns;
}
if (this->commandData != nullptr) {
delete[] this->commandData;
}
}
CommCREATETABLE& operator=(const CommCREATETABLE& comm) {
this->setCommand(comm.fullCommand);
this->setColumns(comm.columns);
this->setCommandData(comm.commandData);
this->setTableName(comm.tableName);
this->setNrOfColumns(comm.nrOfColumns);
this->setNrOfElements(comm.nrOfElements);
this->valid = checkInput(this->commandData, this->columns);
return *this;
}
唯一处理动态内存分配的设置器如下:
void setColumns(const string* columns) {
if (this->nrOfColumns >= 0) {
this->columns = new string[this->nrOfColumns];
memcpy(this->columns, columns, this->nrOfColumns * sizeof(string));
}
else throw EmptyCommandException();
}
void setCommandData(const string* commandData) {
if (this->nrOfElements >= 0) {
this->commandData = new string[this->nrOfElements];
memcpy(this->commandData, commandData, this->nrOfElements * sizeof(string));
}
else throw EmptyCommandException();
}
乍一看,我会说问题出在您的 setColumns
和 setCommandData
函数中。 (我当然可能是错的,我没有尝试 运行 你提供的代码,也没有尝试我所做的更改——所以也可能某处有错字。)
您使用 memcpy
将字符串复制到您的 class 中。但是,在 C++ 内部 string
持有指向实际字符串的指针,因此使用 memcpy
实际上只是复制该指针。因此,一旦原始字符串被删除,您复制到 class 中的指针将不再有效(因为内存已被释放)。因此,一旦您的 class 也被删除,它就会尝试删除已经释放的内存。这可能是您的错误来源。
事实上,如果您在试图操纵 class 的程序中添加行(在删除原始输入字符串之后),问题会更快出现,就像您访问已经释放的内存。这将导致未定义的行为,通常在某个时候以崩溃结束。
一个快速的解决方法是改变你复制数据的方式,通过对每个字符串使用 =
(这样将实际的字符串复制到内存中的一个新位置,而不是复制指针) .
void setColumns(const string* columns) {
if (this->nrOfColumns > 0) { // Creating an array of size 0 is also not a good idea.
this->columns = new string[this->nrOfColumns];
for (int i = 0; i < nrOfColumns; i++) { // You don't need this everywhere.
this->columns[i] = columns[i];
// I don't think naming things the exact same way is good practice.
}
}
else throw EmptyCommandException();
}
void setCommandData(const string* commandData) {
if (this->nrOfElements > 0) { // Creating an array of size 0 is also not a good idea.
this->commandData = new string[this->nrOfElements];
for (int i = 0; i < nrOfElements; i++) { // You don't need this everywhere.
this->commandData[i] = commandData[i];
// I don't think naming things the exact same way is good practice.
}
}
else throw EmptyCommandException();
}
或者,如果您想避免制作副本,您应该查看 move
,但如果您仍在学习,我建议您暂时不要这样做。你很快就会到达那里。
我在程序的最后通过简单地创建指定 class 的实例遇到了这个运行时异常,所以我认为问题出在构造函数、复制构造函数、复制赋值运算符或析构函数。在我有限的 cpp 知识范围内,我已经阅读并遵循了三个规则。
Source.cpp
#include "Header.h"
#include <iostream>
using namespace std;
int main() {
string command = "CREATE TABLE table_name IF NOT EXISTS ((column_1_name,type,default_value), (column_2_name,type,default_value))";
string columns[20] = { "column_1_name,type,default_value", "column_1_name,type,default_value" };
string commandData[9] = { "table_name", "IF NOT EXISTS" };
CommCREATETABLE comm(command, columns, commandData, 2, 2);
}
相关代码来自Header.h
class CommCREATETABLE {
string fullCommand = "";
string* columns = nullptr;
string* commandData = nullptr;
string tableName = "";
int nrOfColumns = 0;
int nrOfElements = 0;
bool valid = false;
构造函数:
CommCREATETABLE(string command, string* columns, string* commandData, int nrOfRows, int nrOfElements) {
this->setNrOfColumns(nrOfRows);
this->setNrOfElements(nrOfElements);
this->setCommand(command);
this->setColumns(columns);
this->setCommandData(commandData);
this->valid = checkInput(this->commandData, this->columns);
this->setTableName(commandData[0]);
}
拷贝构造函数、拷贝赋值运算符、析构函数:
CommCREATETABLE(const CommCREATETABLE& comm) {
this->setNrOfColumns(comm.nrOfColumns);
this->setNrOfElements(comm.nrOfElements);
this->setCommand(comm.fullCommand);
this->setColumns(comm.columns);
this->setCommandData(comm.commandData);
this->setTableName(comm.tableName);
this->valid = comm.valid;
}
~CommCREATETABLE() {
if (this->columns != nullptr) {
delete[] this->columns;
}
if (this->commandData != nullptr) {
delete[] this->commandData;
}
}
CommCREATETABLE& operator=(const CommCREATETABLE& comm) {
this->setCommand(comm.fullCommand);
this->setColumns(comm.columns);
this->setCommandData(comm.commandData);
this->setTableName(comm.tableName);
this->setNrOfColumns(comm.nrOfColumns);
this->setNrOfElements(comm.nrOfElements);
this->valid = checkInput(this->commandData, this->columns);
return *this;
}
唯一处理动态内存分配的设置器如下:
void setColumns(const string* columns) {
if (this->nrOfColumns >= 0) {
this->columns = new string[this->nrOfColumns];
memcpy(this->columns, columns, this->nrOfColumns * sizeof(string));
}
else throw EmptyCommandException();
}
void setCommandData(const string* commandData) {
if (this->nrOfElements >= 0) {
this->commandData = new string[this->nrOfElements];
memcpy(this->commandData, commandData, this->nrOfElements * sizeof(string));
}
else throw EmptyCommandException();
}
乍一看,我会说问题出在您的 setColumns
和 setCommandData
函数中。 (我当然可能是错的,我没有尝试 运行 你提供的代码,也没有尝试我所做的更改——所以也可能某处有错字。)
您使用 memcpy
将字符串复制到您的 class 中。但是,在 C++ 内部 string
持有指向实际字符串的指针,因此使用 memcpy
实际上只是复制该指针。因此,一旦原始字符串被删除,您复制到 class 中的指针将不再有效(因为内存已被释放)。因此,一旦您的 class 也被删除,它就会尝试删除已经释放的内存。这可能是您的错误来源。
事实上,如果您在试图操纵 class 的程序中添加行(在删除原始输入字符串之后),问题会更快出现,就像您访问已经释放的内存。这将导致未定义的行为,通常在某个时候以崩溃结束。
一个快速的解决方法是改变你复制数据的方式,通过对每个字符串使用 =
(这样将实际的字符串复制到内存中的一个新位置,而不是复制指针) .
void setColumns(const string* columns) {
if (this->nrOfColumns > 0) { // Creating an array of size 0 is also not a good idea.
this->columns = new string[this->nrOfColumns];
for (int i = 0; i < nrOfColumns; i++) { // You don't need this everywhere.
this->columns[i] = columns[i];
// I don't think naming things the exact same way is good practice.
}
}
else throw EmptyCommandException();
}
void setCommandData(const string* commandData) {
if (this->nrOfElements > 0) { // Creating an array of size 0 is also not a good idea.
this->commandData = new string[this->nrOfElements];
for (int i = 0; i < nrOfElements; i++) { // You don't need this everywhere.
this->commandData[i] = commandData[i];
// I don't think naming things the exact same way is good practice.
}
}
else throw EmptyCommandException();
}
或者,如果您想避免制作副本,您应该查看 move
,但如果您仍在学习,我建议您暂时不要这样做。你很快就会到达那里。