【问题标题】:Valgrind error invalid read of size 4Valgrind 错误无效读取大小为 4
【发布时间】:2017-12-01 13:59:17
【问题描述】:
void ChoreStack::add(int new_urgency_level, string new_job){
    for(int i = 0; i < length_; i++){
        Chore* temp_chore = chore_array_[i];
        if(temp_chore->level == new_urgency_level){
            temp_chore->joblist.append(new_job+"^");
        }
        chore_array_[i] = temp_chore;
        free(temp_chore);
    }
}

您好,这是 Valgrind 所说的“无效读取大小为 4”的部分。我以前从未学过任何与内存分配相关的东西。谁能详细解释一下为什么会出现内存错误以及如何解决?谢谢!

这是我的声明:

class ChoreStack{
public:
    ChoreStack();
    ~ChoreStack();
    void initialize(int new_urgency_level);
    void add(int new_urgency_level, string new_chore);
    void erase(int erase_level);
    void print();
    void next();
int get_length();
private:
    struct Chore{
        int level;
        string joblist;
    };
    Chore** chore_array_;
    int length_;
    string* split_joblist(string joblist);
    int number_of_chores(string joblist);
};

ChoreStack::ChoreStack(): chore_array_(nullptr), length_(0){
}

ChoreStack::~ChoreStack(){
    delete[] chore_array_;
}

void ChoreStack::initialize(int new_urgency_level){
    delete[] chore_array_;
    chore_array_ = new Chore*[new_urgency_level];
    for(int i = 0; i < new_urgency_level; i++){
        Chore* temp_chore = new Chore;
        temp_chore->level = i+1;
        temp_chore->joblist = "";
        chore_array_[new_urgency_level-i-1] = temp_chore;
        delete temp_chore;
    }
    length_ = new_urgency_level;
    cout << "New priority list with levels 1-" << length_ << " initialized." << endl;
}

这里是 main() 中与 ChoreStack::add() 函数相关的部分:

int main(){
ChoreStack c;
string cmd_line;
string* cmd_ptr = new string[3];
bool initialized = false;
while(true){
    cout << "chores> ";
    getline(cin, cmd_line);
    int cmd_num = 0;
    if(cmd_line.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 ") != string::npos){
        cout << "Error: invalid input." << endl;
    } else {
        int begin_i = 0, space_occurence = 0;
        unsigned int i = 0;
        while(i <= cmd_line.length()){
            if(cmd_line[i] == ' ' || i == cmd_line.length()){
                space_occurence++;
                cmd_num++;
                if(space_occurence == 3){
                    cmd_ptr[cmd_num-1] = cmd_line.substr(begin_i);
                    break;
                } else {
                    cmd_ptr[cmd_num-1] = cmd_line.substr(begin_i, i - begin_i);
                }
                begin_i = i + 1;
            }
            i++;
        }
        string command = cmd_ptr[0];
        if(command == "init"){
            if(cmd_num == 1){
                cout << "Error: the number of priority levels is missing." << endl;
            } else if(cmd_num > 2){
                cout << "Error: too much input for initializing." << endl;
            } else {
                if(cmd_ptr[1].find_first_not_of("1234567890") != string::npos){
                    cout << "Error: the number of priority levels must be an integer larger than 0." << endl;
                } else if(stoi(cmd_ptr[1]) < 1){
                    cout << "Error: it is not possible to create a priority list with 0 or less levels." << endl;
                } else {
                    c.initialize(stoi(cmd_ptr[1]));
                    initialized = true;
                }
            }
        } else if(command == "add"){
            if(!initialized){
                cout << "Error: no priority list is initialized." << endl;
            } else {
                if(cmd_num == 1){
                    cout << "Error: priority level and chore description are missing." << endl;
                } else if(cmd_ptr[1].find_first_not_of("1234567890") != string::npos
                          || stoi(cmd_ptr[1])  < 1
                          || stoi(cmd_ptr[1]) > c.get_length()){
                    cout << "Error: priority level must be an integer between 1-3." << endl;
                } else if(cmd_num == 2){
                    cout << "Error: chore description is missing." << endl;
                } else {
                    c.add(stoi(cmd_ptr[1]), cmd_ptr[2]);
                }
            }
        }

这是错误信息:

invalid read of size 4:
 1.ChoreStack::add(int,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>)

 2.main

Address 0x5a9de70 is 0 bytes inside a block of size 40 free'd
 1. operator delete(void*)

 2. ChoreStack::initialize(int)

 3. main

Block was alloc'd at
 1. operator new(unsigned long)

 2. ChoreStack::initialize(int)

 3. main

而且在这个相同的形式中还有更多的错误......

【问题讨论】:

  • 我们可能需要足够的代码来复制错误。查看完整的valgrind 错误消息也会有所帮助。
  • 您好,很抱歉我不知道如何从QT创建者那里复制错误信息。我是编程新手......
  • 你好大卫,我只是手动输入了错误信息。您现在可以帮我分析我的代码吗?非常感谢!!!
  • 我们可能需要看看initialize 做了什么。这可能是免费后的访问。
  • 代码已添加,先生。非常感谢!!

标签: c++ pointers memory valgrind allocation


【解决方案1】:

这是免费后的经典访问。

void ChoreStack::initialize(int new_urgency_level){
    delete[] chore_array_;
    chore_array_ = new Chore*[new_urgency_level];
    for(int i = 0; i < new_urgency_level; i++){
        Chore* temp_chore = new Chore;
        temp_chore->level = i+1;
        temp_chore->joblist = "";
        chore_array_[new_urgency_level-i-1] = temp_chore;
        delete temp_chore;
    }

仔细查看这段代码。您创建了一个名为temp_chore 的指针。它指向您使用new 分配的对象。然后将temp_chore 的值复制到chore_array_。所以现在数组有一个指向你用new分配的对象的指针。

但是你delete你分配的对象。所以现在,chore_array_ 有一个指向您删除的对象的指针。尝试取消引用此指针是错误的,因为它指向的东西不再存在。

但是在add,我们有:

    Chore* temp_chore = chore_array_[i];
    if(temp_chore->level == new_urgency_level){

所以temp_chore-&gt;level 是试图访问temp_chore 指向的对象的level 成员。但是你 deleted 那个对象。

        // Once you do this,
        chore_array_[new_urgency_level-i-1] = temp_chore;

        // this
        delete temp_chore;

        // does the same thing as this
        delete chore_array_[new_urgency_level-i-1];

        // because they're equal

如果你保留值的集合而不是原始指针的集合,你会发现事情变得容易得多。

【讨论】:

  • 谢谢,但是当我把它改回直接引用 "chore_array_[i]->level = new_urgency_level-i;" 时很抱歉该程序甚至不再运行...
  • 在你修复所有的错误之前,你的程序会表现得奇怪和不可预测。
  • 是的,确实......我一直在努力直到现在......我设法修复了所有错误,除了一个“无效读取大小 8”无缘无故......
  • 但是非常感谢您花时间帮我解决部分问题!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 1970-01-01
  • 2021-12-03
相关资源
最近更新 更多