我的目标是编写一个函数,将AccountInfo类的对象添加到200个元素的AccountInfo对象数组中。数组开始时没有任何对象。 AccountInfo类包含几个字段 - 主要是char *,有几个整数。
经过数小时的尝试,我无法弄清楚出了什么问题。我的代码都符合,但我得到了一个异常
Project1.exe中0x00A164B0处的第一次机会异常:0xC0000005:访问冲突写入位置0x00000000。
在以下一行:
getAccounts()[size()] = AccountInfo(*newUser);
我尽可能地简化了我的代码,同时保留了基本信息。如果提供AccountInfo类的代码会有所帮助,我也可以这样做。
#include <iostream>
using namespace std;
class AccountInfo
{
private:
char* _userLoginName;
char* _password;
unsigned int _uid;
unsigned int _gid;
char* _gecos;
char* _home;
char* _shell;
public:
//Constructor and Destructor
AccountInfo(char* username);
~AccountInfo();
//Also contains getters and setters.
};
//Method Definitions
AccountInfo::AccountInfo(char* username)
{
//Initialize the username and other mandatory fields.
_userLoginName = username;
_home = "/", "h", "o", "m", "e", "/", username;
_shell = "/bin/bash";
}
AccountInfo::~AccountInfo()
{
//Delete dynamically created fields.
delete _userLoginName;
delete _password;
delete _gecos;
delete _home;
delete _shell;
}
class UserDB
{
private:
AccountInfo* _accounts[200];
unsigned int _size;
unsigned int _nextUid;
unsigned int _defaultGid;
AccountInfo* getAccounts();
public:
UserDB();
~UserDB();
void adduser(AccountInfo* newUser);
int size(); // return the number of accounts stored (_size)
};
AccountInfo* UserDB::getAccounts()
{
return _accounts[200];
}
UserDB::UserDB()
{
_size = 0;
_nextUid = 1001;
_defaultGid = 1001;
}
int UserDB::size()
{
return _size;
}
void UserDB::adduser(AccountInfo* newUser)
{
getAccounts()[size()] = AccountInfo(*newUser);
}
int main() //main method
{
UserDB users;
AccountInfo *x = new AccountInfo("Joe");
//This creates an AccountInfo object with one of its
//char* fields initialized to "Joe".
users.adduser(x);
return 0;
}
我做错了什么?我该如何解决?
答案 0 :(得分:2)
您正在创建一个新的临时对象,以添加指向:
的指针getAccounts()[size()] = AccountInfo(*newUser);
为什么要解除引用newUser
,只复制构造一个临时的?
你可能想要:
getAccounts()[size()] = newUser;
此外,size
并不是该功能的一个很好的名称 - 它使得它听起来好像您每次都在为N+1
位置编制索引。 numAccounts
或类似的可能更合适。
不要忘记增加此计数器,并检查您是否达不到200
限制!
此外,通过添加的代码,我看到您尝试将char*
类型的变量设置为"something"
。你只能在初始化时这样做;你的构造函数需要在初始化列表中以这种方式设置_shell
等,而不是在构造函数体中:
AccountInfo::AccountInfo(char* newUser) : _shell("/bin/bash") {/**/}
答案 1 :(得分:1)
无法以权威方式回答您的问题,因为您没有显示size()和getAccounts()方法的内容。
但可以做出一个很好的猜测:
void UserDB::adduser(AccountInfo* newUser)
{
getAccounts()[size()] = AccountInfo(*newUser);
}
要使此代码起作用,getAccounts()方法必须返回指向已初始化的AccountInfo对象的现有数组的指针,此代码将使用新构造的对象替换数组中AccountInfo对象的现有实例。
这并没有多大意义。
此外:
AccountInfo* _accounts[200];
这声明了一个200个元素的指向AccountInfo对象的指针数组。这不会声明一个包含200个AccountInfo对象的数组。
我怀疑你的getAccounts()方法以某种方式返回_accounts
类成员。如果是这样,这不可能以这种方式工作。至少,除非构造函数在堆上动态分配实际数组,否则将所有这些指针初始化为指向动态分配数组中的相应元素,然后始终返回第零个类实例的地址。
这是它的作用吗?
答案 2 :(得分:0)
AccountInfo* _accounts[200];
由于_accounts[index of element]
未使用NEW
创建,因此_accounts[index of element]
为NULL。
请在getAccounts()[size()]
getAccounts()[size()] = AccountInfo(*newUser);
答案 3 :(得分:0)
AccountInfo* UserDB::getAccounts()
{
// This returns a pointer to the element as index 200,
// which is past the end of the array and 'undefined behavior'
return _accounts[200];
}
由于您声明了一个200 AccountInfo 指针的数组(即,不是200 AccountInfo 对象的数组),您应该返回指向该成员的指针。
AccountInfo** UserDB::getAccounts()
{
return _accounts;
}
此外,假设 addUser 函数旨在取得给定指针的所有权,则应更新如下:
void UserDB::adduser(AccountInfo* newUser)
{
// This function also needs to guard against size() returning
// values larger than 199 and increment the size
// This takes ownership of the pointer and the destructor needs
// to delete the memory (see 'rule of three' below)
getAccounts()[size()] = newUser;
}
此外,由于这是C ++,您应该使用标准容器或智能指针来处理此内存管理。例如:
此外,如果 UserDB 类实际上是拥有 AccountInfo 指针,那么您应该知道rule of three。
如果C ++ 11可用,那么你也可以实现移动语义。
答案 4 :(得分:0)
即使这个问题已经两年了,我想提一个没有人提出过的答案。 在我看来,如果可能的话,你应该使用boost :: static_vector(http://www.boost.org/doc/libs/1_64_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.static_vector)。它具有您的代码尝试具有的相同行为。它构造一个具有固定数量元素的静态数组,并提供与std :: vector相同的接口。如果你尝试推送的元素多于可能,它就像std :: vector一样抛出一个out_of_memory异常。