【问题标题】:C++ Invalid read size 4 valgrindC++ 无效读取大小 4 valgrind
【发布时间】:2016-04-11 15:35:54
【问题描述】:

由于某种我无法弄清楚的原因,我收到“无效的读取大小 4”错误。我在网上搜索了答案,但它对我的代码并没有真正的帮助。总结一下我的代码的作用,它是一个股票交易模拟器。将向用户显示选项,然后他们可以选择他们想做的事情。现在我遇到了“卖出股票”的问题。这是它的样子。

Stock* newStock = new Stock(); 
view->getStockData(newStock);

Stock* s = stocks->findElement(newStock);

if(s->getAOS()-newStock->getAOS() > 0) { // There is still some shares remaining
    // Haven't done this yet        

} else if (s->getAOS()-newStock->getAOS() == 0) { // There is no shares remaining
        double result = s->calculate(newStock->getPrice(), s->getPrice(), s->getAOS());
        view->printResults(result, 0);

        stocks->remove(newStock);

} else { // Resulted with a negative value
    // Haven't done this yet    
}

view->getStockData(newStock);看起来像这样:

void UImanager::getStockData(Stock* stock) {
    // Initializing all the stock data
    string    str = "";
    string    symbol, companyName;
    double    price;
    int       amountOfShares;

    cout << endl << "Enter the stock's symbol (e.g. AAPL):  ";
    getline(cin, symbol);

    cout << endl << "Enter the companies name:   ";
    getline(cin, companyName);

    cout << endl << "Enter the price of the stock:   ";
    getline(cin, str);
    stringstream ss(str);
    ss >> price;
    str = "";

    cout << endl << "Enter the amount of shares:    ";
    getline(cin, str);
    stringstream ss1(str);
    ss1 >> amountOfShares;
    str = "";

    Stock* tmpStock = new Stock(symbol, companyName, price, amountOfShares); 
    *stock = *tmpStock;
    delete tmpStock;
}

股票类如下所示:

Stock::Stock(string s, string c, double p, int aOS) {
    symbol = s;
    companyName = c;
    price = p;
    amountOfShares = aOS;
    fee = 10;
}

string Stock::getSymbol()      { return symbol; }
string Stock::getCompanyName() { return companyName; }
double Stock::getPrice()       { return price; }
int    Stock::getAOS()         { return amountOfShares; }
int    Stock::getFee()         { return fee; }

bool Stock::operator==(Stock& s) {
    if (this->getSymbol() == s.getSymbol()) {
        return true;
    }   

    return false;
}

// More below this, but that code doesn't matter for this problem

我将股票存储在我制作的模板 Dlist 中。这是 findElement(T*):

template <class T>
T* Dlist<T>::findElement(T* item) {
    Node<T>* currNode = head;

    while (currNode != 0) { // iterate through the Dlist
        if (currNode->data == item) { // uses the operator overloaded == from Stock
            return currNode->data;
        }

        currNode = currNode->next;
    }

    // gets to this point if nothing was found
    return 0;
} 

这是 valgrind 所说的:

==2459== Invalid read of size 4
==2459==    at 0x804A4EC: Stock::getAOS() (in /home/student/Desktop/Stock Paper Trading/spt)
==2459==    by 0x8049356: SPTcontrol::launch() (in /home/student/Desktop/Stock Paper Trading/spt)
==2459==    by 0x8048F8D: main (in /home/student/Desktop/Stock Paper Trading/spt)
==2459==  Address 0x10 is not stack'd, malloc'd or (recently) free'd
==2459== 
==2459== 
==2459== Process terminating with default action of signal 11 (SIGSEGV)
==2459==  Access not within mapped region at address 0x10
==2459==    at 0x804A4EC: Stock::getAOS() (in /home/student/Desktop/Stock Paper Trading/spt)
==2459==    by 0x8049356: SPTcontrol::launch() (in /home/student/Desktop/Stock Paper Trading/spt)
==2459==    by 0x8048F8D: main (in /home/student/Desktop/Stock Paper Trading/spt)

所以我知道它告诉我在 Dlist 中找到我的股票类后访问信息有问题,但我真的不明白为什么或如何解决它?任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 我注意到您没有检查 Stock* s = stocks-&gt;findElement(newStock) 是否返回 null
  • 是的,我检查了 s 是否为空,我发现它是。现在我正在跟踪问题,似乎问题出在我的运算符重载 == 因为我将 cout 用于 item->getSymbol() 和 currNode->data->getSymbol() 并且它们都是“AAPL” (我用于测试的内容)但似乎 currNode->data == item 由于某种原因返回 false

标签: c++ segmentation-fault valgrind


【解决方案1】:

在我看来 s 是一个空指针,因为 Dlist::findElement 返回一个空指针。

主要线索是 valgrind 抱怨的地址。你看到它说“地址 0x10 没有被堆栈、malloc 或最近释放”吗?真实地址如此接近于零是非常不寻常的(阅读:几乎完全闻所未闻);这几乎总是意味着您的代码遇到了一个空指针,该指针在大多数系统上恰好由零地址表示,然后对其进行了一些算术运算(例如,如果 Stock 在地址 0 处,那么它的amountOfShares?在地址 16 = 0x10,也许)。

您可以通过添加一些显式检查空指针的代码来检查这一点,或者通过在调试器中运行您的代码并单步执行它。

如果我的猜想是正确的(或者如果它是错误的,但一些类似的猜想是正确的)将是您从 Dlist::findElement 获得空指针的原因。但我会让你自己解决这个问题。

【讨论】:

  • 哦,好吧,现在我知道从哪里开始修复它了。谢谢
  • 问题似乎是我的运算符重载函数,但我不明白为什么?在 findElement 中,我将 if(currNode->data == item) 更改为 if(currNode->data->getSymbol() == item->getSymbol()) (这显然违背了模板化 dlist 的目的)只是为了测试它它确实有效吗?似乎它甚至没有调用运算符重载 == 因为我将 cout 语句放入其中并且它们从未打印到控制台?你知道它为什么这样做吗?
  • 我们没有 Node 类的定义,但如果你能说像 currNode-&gt;data-&gt;getSymbol() 这样的话,那么我认为 Node&lt;T&gt;::data 的类型是 T * 而不是 T .在这种情况下,当您尝试比较其中两个时,您将获得指针比较。您的operator== 用于比较两个Stocks,并且在比较两个Stock*s 时不会被调用。
  • 做到了!我将 if(currNode->data == item) 更改为 if(*(currNode->data) == *item) 并且它现在完美运行!非常感谢!
  • 不客气。您可能想接受我的回答,这将为我们双方带来一些额外的声望点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-21
  • 1970-01-01
相关资源
最近更新 更多