簡體   English   中英

嘗試讀取/寫入Graphviz DAG值的工作證明會導致段錯誤

[英]Attempt at proof of work reading/writing Graphviz DAG values causes segfault

更新:使用-g編譯並檢查有問題的每一行后,現在它已設法在系統級頭文件中進行segfault:

Program received signal SIGSEGV, Segmentation fault.
__gnu_cxx::new_allocator<char*>::construct<char*, char* const&> (this=0x7fffffffdec0, 
__p=0x5555557702f0, __args#0=<error reading variable>)
at /usr/include/c++/8.1.1/ext/new_allocator.h:136
136             { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

這是我以前從未見過的東西。

因此,我有一個非常簡單的C ++程序,該程序至少嘗試同時寫入文件和從文件中讀取文件,以確保DA​​G中絕對沒有重復值(更改了變量名以保護個人交易)秘密):

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>

struct parsedline {
    unsigned long long pre_edge;
    unsigned long long post_edge;
};

std::vector<parsedline> readfile(std::string name) {
    //create array of parsedlines for later use
    std::vector<parsedline> edges;

    //count lines and create array of lines
    int linecount = 0;
    std::vector<char*> lines;
    std::ifstream dag(name);
    std::string ul;

    while (std::getline(dag, ul)) {

        //convert to c_str immediately to avoid errors with atoi
        std::istringstream thisline;
        thisline.str(ul);
        lines[linecount] = const_cast<char*>(thisline.str().c_str());
        ++linecount;

    }

    //drop block definition in graphviz file representing DAG
    int max_readable_line = sizeof(lines) - 2;
    std::vector<char*> readable_lines;

    for (int i = 0; i < max_readable_line; i++) {

        //shift index to skip line 1
        int rlindex = i+1;
        readable_lines[i] = lines[rlindex];

    }

    //read integers from each line, store them in array of parsedline objects
    for (int j = 0; j < max_readable_line; j++) {

        int edge_begin, edge_end;
        if (std::sscanf(readable_lines[j], "   %d -> %d", &edge_begin, &edge_end)) {
            edges[j].pre_edge = edge_begin;
            edges[j].post_edge = edge_end;
        }

    }
    return edges;
}

int main (int argc, char **argv) {

    unsigned long long minperrank = atoi(argv[1]);
    unsigned long long maxperrank = atoi(argv[2]);
    unsigned long long minranks = atoi(argv[3]);
    unsigned long long maxranks = atoi(argv[4]);
    double edgechance = atof(argv[5]);
    std::string filedest(argv[6]);

    unsigned long long i,j,k,l,nodes = 0;
    std::srand(time(NULL));

    unsigned long long ranks = minranks + (std::rand() % (maxranks - minranks + 1));

    std::ofstream dagout(filedest, std::ofstream::out);
    std::vector<parsedline> lines = readfile(filedest);

    dagout << "digraph {" << std::endl;

    for(i = 0; i < ranks; i++) {
        unsigned long long newnodes = minperrank + (rand() % (maxperrank - minperrank + 1));

        for (j = 0; j < nodes; j++) {

            for (k = 0; k < newnodes; k++) {

                unsigned long long checkval = std::rand() % 100;

                if (checkval < edgechance) {

                    for (l = 0; l < sizeof(lines); l++) {

                        //each new member must be a nonce
                        unsigned long long pree = lines[l].pre_edge;
                        unsigned long long poste = lines[l].post_edge;
                        if (checkval != pree) {

                            if (checkval != poste) {

                                dagout << "   " << j << " -> " << k+nodes << ";" << std::endl;

                            }

                        }

                    }

                }

            }

        }

        nodes += newnodes;

    }

    dagout << "}" << std::endl;
    return 0;
}

這樣編譯就可以了,但是當我嘗試運行它時:

[realkstrawn93@archlinux Desktop]$ ./gendag 10 10 10 10 0.1 test.gv
Segmentation fault (core dumped)
[realkstrawn93@archlinux Desktop]$ 

這是gdb的輸出-它表示它在readfile函數中,但沒有確切說明它在該函數中的位置:

[realkstrawn93@archlinux Desktop]$ gdb gendag
GNU gdb (GDB) 8.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gendag...(no debugging symbols found)...done.
(gdb) r 10 10 10 10 0.1 test.gv
Starting program: /home/realkstrawn93/Desktop/gendag 10 10 10 10 0.1 test.gv

Program received signal SIGSEGV, Segmentation fault.
0x0000555555555675 in readfile(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >) ()

我需要知道段錯誤在該函數中的確切位置。

//count lines and create array of lines
int linecount = 0;
std::vector<char*> lines;  <--
std::ifstream dag(name);
std::string ul;

while (std::getline(dag, ul)) {

    //convert to c_str immediately to avoid errors with atoi
    std::istringstream thisline;
    thisline.str(ul);
    lines[linecount] = const_cast<char*>(thisline.str().c_str()); <--
    ++linecount;

}

您正在初始化之前訪問lines[linecount] 盡管向量已初始化為空,但其元素未初始化。 采用

lines.push_back(const_cast<char*>(thisline.str().c_str()));

如果您所需要做的就是在向量的末尾附加一個元素,而不是訪問運算符( [] )。

否則,如果必須按元素的位置訪問元素,則首先通過將參數傳遞給構造函數來進行初始化,如in

std::vector<char*> lines(max_lines);

它將初始化向量以包含max_lines空對象。

當程序訪問不屬於它的內存時,就會發生分段錯誤。 由於向量總是分配在堆上,因此訪問超出其范圍的任何數據都將導致段錯誤。

事實證明,在繼續之前,我必須檢查數組的大小是否為0。 否則,它是一個空指針取消引用:

if (lines.size() == 0) {

    dagout << "   " << j << " -> " << k+nodes << ";" << std::endl;

} else {

    //each new member must be a nonce
    unsigned long long pree = lines.at(l).pre_edge;
    unsigned long long poste = lines.at(l).post_edge;
    if (std::rand() % 100 != pree) {

        if (std::rand() % 100 != poste) {

            dagout << "   " << j << " -> " << k+nodes << ";" << std::endl;

        }

    }

}

但是,現在我遇到了一個無限循環問題-這是一個完全不相關的問題,我可以自己解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM