我有一个指向结构的指针向量,这些结构存储在我学校项目的另一个向量中。当我尝试使用指针更改结构中的元素时,由于某种原因导致未定义的行为。我删除了与下面问题相关的部分代码。
#include <vector>
#include <string>
#include <iostream>
class someException{};
enum class ProcessStatus{
RUNNING,
READY
};
struct Process{
int priority;
std::string PID;
ProcessStatus status;
Process(){
status = ProcessStatus::READY;
}
};
struct ReadyList{
std::vector<Process*> priority1;
std::vector<Process*> priority0;
};
class ProcessManager{
private:
std::vector<Process> processList;
ReadyList readyList;
public:
ProcessManager(){};
void createProcess(std::string PID, int priority){
Process process;
process.priority = priority;
process.PID = PID;
if (priority == 0)
process.status = ProcessStatus::RUNNING;
processList.push_back(process);
switch(priority){
case 0:
readyList.priority0.push_back(&processList.at(processList.size()-1));
break;
case 1:
readyList.priority1.push_back(&processList.at(processList.size()-1));
break;
default:
throw someException();
}
schedule(findRunningProcess());
}
void printProcesses(){
std::cout<<"ReadyList results:"<<std::endl;
for(auto &process: readyList.priority0){
std::cout << "Process: "<< process->PID << " , Priority: "<<process->priority;
if (process->status == ProcessStatus::RUNNING)
std::cout << ", Status: RUNNING"<< std::endl;
else
std::cout <<", Status: READY"<<std::endl;
}
for(auto &process: readyList.priority1){
std::cout << "Process: "<< process->PID << " , Priority: "<<process->priority;
if (process->status == ProcessStatus::RUNNING)
std::cout << ", Status: RUNNING"<< std::endl;
else
std::cout <<", Status: READY"<<std::endl;
}
std::cout<<"ProcessList results: "<<std::endl;
for(auto &process: processList){
std::cout << "Process: "<< process.PID << " , Priority: "<<process.priority;
if (process.status == ProcessStatus::RUNNING)
std::cout << ", Status: RUNNING"<< std::endl;
else
std::cout <<", Status: READY"<<std::endl;
}
}
private:
void schedule(Process* currentProcess){
Process* highestPriorityProcess;
if (readyList.priority1.size()>0)
highestPriorityProcess = readyList.priority1[0];
else
highestPriorityProcess = readyList.priority0[0];
if (currentProcess->priority < highestPriorityProcess->priority){
currentProcess->status = ProcessStatus::READY;
highestPriorityProcess->status = ProcessStatus::RUNNING;
}
}
Process* findRunningProcess(){
for (auto &process: processList){
if (process.status == ProcessStatus::RUNNING){
return &process;
}
}
return nullptr;
}
};
int main(){
ProcessManager pm = ProcessManager();
pm.createProcess("ROOT", 0);
std::cout<<"After creating process ROOT"<<std::endl;
pm.printProcesses();
pm.createProcess("A", 1);
std::cout<<"After creating process A"<<std::endl;
pm.printProcesses();
return 0;
};
输出结果如下:
After creating process ROOT
ReadyList results:
Process: ROOT , Priority: 0, Status: RUNNING
ProcessList results:
Process: ROOT , Priority: 0, Status: RUNNING
After creating process A
ReadyList results:
Process: ROOT , Priority: 0, Status: RUNNING
Process: A , Priority: 1, Status: RUNNING
ProcessList results:
Process: ROOT , Priority: 0, Status: READY
Process: A , Priority: 1, Status: RUNNING
ProcessList设置为正确的值,进程A正在运行并处理ROOT就绪,但由于某种原因,ReadyList保持不变。在我的原始代码中,读取列表中进程ROOT的PID字符串值变为空,并且在更改状态后,我在此示例中遗漏的进程中存储的映射值也被清除。 我还测试了直接使用readyList指针进行更改,而不是使用findRunningProcess函数返回的指针,它没有修复PID和映射值的问题,但在进程状态中导致了一些其他未定义的行为。我对可能导致此问题的想法不满意,请帮忙!非常感谢。
答案 0 :(得分:6)
每次你:
processList.push_back(process);
vector
可能会调整大小。这意味着支持vector
的数据存储区将被复制到新的数据存储区中,然后被丢弃。这将为您留下另外两个vector
,其中包含已释放并可能已重新分配的内存指针。
processList
是使用std::list
或std::deque
的好地方,因为它们在增长时不会使指针无效。 std::deque
应具有一些性能优势,因为它往往具有更好的空间局部性。
另一种方法是让其他两个vector
存储processList
中的进程索引,因为只要您只撤回并且不删除进程,它们就不会更改。
在任何一种情况下,从processList
删除进程而不确定它们是否已首先从其他vector
中删除,这将是一个坏主意。 std::deque
处于劣势,如果你删除,因为这会使指针无效。
答案 1 :(得分:1)
我怀疑ProcessManager
中的进程列表向量在某个时刻正在调整大小,导致它必须创建一个新的内部数据结构并复制内容,让你的旧指针悬空。
如上所述:http://en.cppreference.com/w/cpp/container/vector/push_back
如果新的size()大于capacity()那么所有的迭代器和 引用(包括过去的结束迭代器)无效。 否则只有过去的迭代器无效。