【问题标题】:Access violation error thrown while debugging C++ code调试 C++ 代码时引发访问冲突错误
【发布时间】:2016-12-07 09:13:02
【问题描述】:

我正在尝试构建解析器并将值存储在 C++ 中的链表中。我收到以下我无法解决的错误,我查看了其他 Stack Overflow 链接,但找不到正确的答案。

我收到以下错误:

在 parse_and_store.exe 中的 0x000000013FCF3954 处引发异常:0xC0000005:访问冲突读取位置 0x0000000000000018。

如果有这个异常的处理程序,程序可以安全地继续。

我的 parses_and_store.cpp 代码如下:

#include "stdafx.h"

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <direct.h>

// I don't recommend using the std namespace in production code.
// For ease of reading here.
using namespace std;

struct node {
    string data;
    node *next;
};

// You could also take an existing vector as a parameter.
vector<string> split(string str, char delimiter) {
    vector<string> internal;
    stringstream ss(str); // Turn the string into a stream.
    string tok;

    while (getline(ss, tok, delimiter)) {
        internal.push_back(tok);
    }

    return internal;
}

void printList(node* head)
{
    node *tmp = head;

    while (tmp->next != NULL) {
        tmp = tmp->next;
        cout << tmp->data << endl;
    }
}

int main() {
    string myCSV = "one two three four";

    char *buffer = NULL;
    node *n = NULL;

    // Get the current working directory: 
    if ((buffer = _getcwd(NULL, 0)) == NULL)
        perror("_getcwd error");
    else
    {
        //printf("%s \nLength: %d\n", buffer, strlen(buffer));
        printf("%s\n\n", buffer);
        free(buffer);
    }

    std::ifstream file("differential_pair.txt");
    std::string str;
    while (std::getline(file, str))
    {
        // Process str
        cout << str << endl;
        n = new node;
        vector<string> sep = split(str, ' ');
        for (int i = 0; i < sep.size(); i++)
        {
            cout << sep[i] << endl;
            //std::string str(sep[i].begin(), sep[i].end());
            cout << sep.size() << endl;
            std::cin.get();
            n->data = sep[i];
            n = n->next;
        }
    }

    printList(n);

    // If using C++11 (which I recommend)
    /* for(string t : sep)
    *  cout << t << endl;
    */
    file.close();

    std::cout << "\nText verified!" << std::endl;
    std::cin.get();
    return 0;
}

我的“differential_pair.txt”文件包含以下数据:

VCC 7 0 12
VEE 8 0 -12
VIN 1 0 AC 1
RS1 1 2 1K
RS2 6 0 1K
Q1 3 2 4 MOD1

【问题讨论】:

  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行浏览您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • 好的,我会用调试器检查。
  • 调试器只是将我直接带到“xstring”文件,它会将我引导到以下语句: if (this->_Myres() _Mysize( )); // 重新分配以增长
  • 请注意,请求紧迫性就像在问题上画一个大的反对票目标 - 不要这样做!对于志愿者来说,这从不紧急。
  • 看起来你正在取消引用一个未初始化的指针。

标签: c++ arrays vector linked-list structure


【解决方案1】:

您可以尝试分析代码中n 的使用情况。 在main 的开头你有node *n = NULL; - 很好的初始化。

然后,通过每行的循环拆分元素并尝试将其存储到列表中。看看下面的注释行:

while (std::getline(file, str))
{
    // Process str
    cout << str << endl;
    n = new node; // 1
    vector<string> sep = split(str, ' ');
    for (int i = 0; i < sep.size(); i++)
    {
        cout << sep[i] << endl;
        //std::string str(sep[i].begin(), sep[i].end());
        cout << sep.size() << endl;
        std::cin.get();
        n->data = sep[i]; //2
        n = n->next; //3
    }
}

对于从文件(1) 读取的每个新行,您将新值分配给n。可能这不是你想要的。

(2) 中,您将读取的元素从行分配给看起来很好的数据字段,但随后在(3) 中用n-&gt;next 指向的内容替换n,这可能包含垃圾。

之后您可能想使用printList(n); 打印整个列表,但由于n 的每一行都有一个新值,并且可能指向的不是您所期望的,因此代码会失败。

如果您想要文件中所有元素的单个列表,则应将 n 视为列表的 head 元素。此外,添加一个附加变量以指向当前列表元素(这样您就不会丢失列表根元素)。 在内部 for 循环中,您应该为每个条目创建节点元素

for(...){
    //....
    node* entry = new node;
    entry->data = sep[i];
    current->next = entry;
    current = entry;
}

注意,您应该确保在创建第一个 node 时,n(被视为头/根)和 current 都指向相同的数据。

例如,在while 循环之前,您可以放置​​:

node* current = new node;
node* n = current;

但是,这样第一个列表条目将不包含任何数据,它仅用于指向数据实际开始的位置 - 这应该在打印函数中处理。另一方面,您可以跳过上述内容并在 for 循环内进行检查,例如:

node* entry = new node;
if (!n)
    n = current = entry;
// ...

这既不漂亮也不优雅,因为每次循环迭代都会对条件进行评估,并且只会在第一次出现true,但它应该可以完成这项工作。

一般来说,如果您不想使用标准containers 来解决您的问题,您仍然可以尝试编写一个内部使用您定义的结构的类。这样你可以隐藏不必要的实现细节:在内部存储头部,正确处理清理过程(现在根本没有完成)等等,并使你的容器更易于使用。

【讨论】:

  • 我通过给出 str="VCC 7 1 2" 进行了检查,它为“VCC”的“1”值和“7”提供了访问冲突,它工作正常。它发生在字符串中的第三个元素意味着“sep [2]”为什么会这样?
  • 即使你修复了n = n-&gt;next,你最终还是会得到一个仅包含解析文件中最后一个元素的列表。因为对于每个解析的行,您都创建了全新的node,并且在for 循环内,您每次迭代都会写入相同的data 元素。还表示 printList(node* head) 需要一个 head 元素,但您传递 n 您将其视为代码中的最后一个元素
  • 是的,我现在面临同样的问题,节点中只有最后一个元素。如何解决这个问题?
  • 正如我在答案中所写,您必须在每次循环迭代中创建node* entry = new node;
  • 我需要多个链表,如 VCC->1->2->3 和第二个 VEE->3->2->1 类似。创建一个条目只会创建一个链表,但我需要多个链表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多