【问题标题】:No compilation errors and, it seems, no syntax errors -- but garbage is displayed?没有编译错误,似乎也没有语法错误——但是显示垃圾?
【发布时间】:2017-09-23 18:59:35
【问题描述】:

工作代码固定及以下

这是整个 .cpp。有什么想法为什么在调用重载 void display(const Kingdom kingdoms[], size_t count) 函数时打印出纯垃圾?

File Kingdom.h
#ifndef KINGDOM_H
#define KINGDOM_H
#include <cstdlib>
// TODO: sict namespace
namespace sict
{
    // TODO: define the structure Kingdom in the sict namespace

        struct Kingdom {
            char m_name[32];
            int m_population;
        };
        // TODO: declare the function display(...),
        //         also in the sict namespace
        void display(const Kingdom& pKingdom);
        void display(const Kingdom kingdoms[], size_t count);
}


#endif

File Kingdom.cpp
#include <iostream>
#include <cstdlib>
#include "Kingdom.h"
using namespace std;
// TODO: the sict namespace
namespace sict
{
    // TODO:definition for display(...)

    void display(const Kingdom& pKingdom) {
        cout << pKingdom.m_name << ", " << "population " << pKingdom.m_population << endl;
    }

    void display(const Kingdom kingdoms[], size_t count) {
        cout << "------------------------------" << endl;
        cout << "Kingdoms of SICT" << endl;
        cout << "------------------------------" << endl;
        int pop = 0;
        for (size_t i = 0; i < count; i++) {
            cout << i + 1 << ". ";
            display(kingdoms[i]);
                pop += kingdoms[i].m_population;
        }
        cout << "------------------------------" << endl;
        cout << "Total population of SICT: " << pop << endl;
        cout << "------------------------------";
    }
}


    File main.cpp
    #include <iostream>
    #include <cstring> //for size_t definition
    #include <vector>
    #include "Kingdom.h"

    using namespace std;
    using namespace sict;

    void read(Kingdom&);

    int main() {
        int count = 0; // the number of kingdoms in the array

        // TODO: declare the pKingdom pointer here (don't forget to initialize it)
        Kingdom *pKingdom = nullptr;
        cout << "==========\n"
            << "Input data\n"
            << "==========\n"
            << "Enter the number of Kingdoms: ";
        cin >> count;
        cin.ignore();

        if (count < 1) return 1;

        // TODO: allocate dynamic memory here for the pKingdom pointer
        pKingdom = new Kingdom[count];
        for (int i = 0; i < count; ++i) {
            cout << "Kingdom #" << i + 1 << ": " << endl;
            // TODO: add code to accept user input for Kingdom i
            read(pKingdom[i]);
        }
        cout << "==========" << endl << endl;

        // testing that "display(...)" works
        cout << "------------------------------" << endl
            << "The 1st Kingdom entered is" << endl
            << "------------------------------" << endl;
        display(pKingdom[0]);
        cout << "------------------------------" << endl << endl;

        // expand the array of Kingdoms by 1 element
        count = count + 1;
        Kingdom *cpy_pKingdom = nullptr;
        // TODO: allocate dynamic memory for count + 1 Kingdoms
        cpy_pKingdom = new Kingdom[count];
        // TODO: copy elements from original array into this newly allocated array
        for (int i = 0; i < count; i++) {
            cpy_pKingdom[i] = pKingdom[i];
        }
        // TODO: deallocate the dynamic memory for the original array
        delete[] pKingdom;
        // TODO: copy the address of the newly allocated array into pKingdom pointer
        pKingdom = cpy_pKingdom;
        // add the new Kingdom
        cout << "==========\n"
             << "Input data\n"
             << "==========\n";
        cout << "Kingdom #" << count << ": " << endl;
             // TODO: accept input for the new element in the array
             read(pKingdom[count - 1]);
        cout << "==========\n" << endl;

        // testing that the overload of "display(...)" works
        display(pKingdom, count);
        cout << endl;

        // TODO: deallocate the dynamic memory here
        //delete[] pKingdom;
        //delete[] cpy_pKingdom;
        getchar();
        return 0;
    }

    // read accepts data for a Kingdom from standard input
    //
    void read(Kingdom& pkingdom) {
        cout << "Enter the name of the Kingdom: ";
        cin.get(pkingdom.m_name, 32, '\n');
        cin.ignore(2000, '\n');
        cout << "Enter the number of people living in " << pkingdom.m_name << ": ";
        cin >> pkingdom.m_population;
        cin.ignore(2000, '\n');

【问题讨论】:

  • 使用 std::vector!你不要复制你的数组!
  • 扩展数组的代码是错误的。
  • 这并没有解决问题,但是您真的需要std::endl 需要的额外内容吗? ’\n’ 结束一行。

标签: c++ garbage


【解决方案1】:

明显的违规行(可能还有其他行)是

cpy_pKingdom = new Kingdom[count + 1];
cpy_pKingdom = pKingdom;
delete[] pKingdom;
pKingdom = cpy_pKingdom;

cpy_pKingdom = pKingdom 的赋值是指针赋值,不复制任何数组。它还会丢弃新表达式的结果,这意味着cpy_pKingdompKingdom 都具有pKingdom 的原始值。

delete [] pKingdom 然后释放pKingdom 指向的内存,这也是(由于前面的赋值cpy_pKingdom = pKingdomcpy_Kingdom 指向的内存。

这四行的最终结果是new Kingom[count + 1] 被泄露(它已分配,从未释放,但也无法访问),pKingdomcpy_pKingdom 都指向已释放的内存。

更糟糕的是,下一个对pKingdom 执行任何操作的语句是

read(pKingdom[count + 1]);

从文件中读取数据到不存在的pKingdom[count + 1]。请记住——即使前面的代码使pKingdom 指向new Kingdom[count + 1] 分配的内存——这也将超过该内存的末尾。还有未定义的行为。

然后我们开始

 display(pKingdom, count);

它将访问相同的不存在的内存以打印出那里的数据。

在此处显示垃圾是代码中一个或多个前面未定义行为实例的次要后果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 2018-06-10
    相关资源
    最近更新 更多