Nano Hash - криптовалюты, майнинг, программирование

Ошибка сегментации в моей программе на C++

Я делаю решатель для игры Flood-It (кажется, также известной как Blobs). Программа компилируется и работает нормально до самого конца. . . Я делаю последний «cout» (а затем добавляю «return 0» без какого-либо эффекта) в конце моей функции main (), и появляется сообщение «FloodItSolver.exe перестал работать ...»

Когда я делаю «gdb FloodItSolver», а затем «r», я заканчиваю следующим выводом:

Did not complete in 25 turns.
Program received signal SIGSEGV, Segmentation fault.
0x6fc5b222 in libstdc++-6!_ZN9__gnu_cxx18__exchange_and_addEPVii () from C:\MinGW\bin\libstdc++-6.dll

Эта часть о «Не завершено» — это последнее, что я хочу сказать.

ОБНОВЛЕНИЕ: Вот результат выполнения команды «backtrace» в gdb:

(gdb) backtrace
#0  0x6fc5b222 in libstdc++-6!_ZN9__gnu_cxx18__exchange_and_addEPVii () from C:\MinGW\bin\libstdc++-6.dll
#1  0x6fcbd66e in libstdc++-6!atomic_flag_test_and_set_explicit () from C:\MinGW\bin\libstdc++-6.dll
#2  0x00401fee in __tcf_2 () at flooditsolver.cpp:9
#3  0x75b3c3e9 in msvcrt!isspace () from C:\Windows\syswow64\msvcrt.dll
#4  0x75b437df in msvcrt!_cexit () from C:\Windows\syswow64\msvcrt.dll
#5  0x00000000 in ?? ()
(gdb)

Это не имеет смысла, потому что я достиг конца моей функции main()! Зачем тут SegFault?

Мой код:

#include <iostream>
#include <fstream>
using namespace std;

//  GLOBAL---------------------------------------------------------------------
int rgbPos, scPos, color, grid[14][14];
ifstream file("Floodit.txt");
bool isFlood[14][14];
string line;
//  END GLOBAL-------------------------------------------------------------

//  Function Pool ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//  HighestBorderCount(), NonFloodColorsLeft(), CanEliminateAColor(), etc...
//  Gather a list of variables you consider when planning your next move, then make a function for it
//  So far I only have HighestBorderCount()

int HighestBorderCount()
{
    int highest=0, returnMe, countColors[6]={0,0,0,0,0,0};
    bool paddedBorder[16][16], border[14][14];
    for(int x=0;x<16;x++) {for(int y=0;y<16;y++) {paddedBorder[x][y]=false;}}
    for(int x=0;x<14;x++) {for(int y=0;y<14;y++) {border[x][y]=false;paddedBorder[x+1][y+1]=isFlood[x][y];}}    // Create copy of isFlood, zero out border[][]
    for(int x=0;x<14;x++) 
    {
        for (int y=0;y<14;y++) 
        {
            if( (!paddedBorder[x+1][y+1]) && (  (paddedBorder[x][y+1]) || (paddedBorder[x+1][y]) || (paddedBorder[x+2][y+1]) || (paddedBorder[x+1][y+2])    )   ) border[x][y]=true;
            if(border[x][y])
            {
                switch(grid[x][y])
                {
                    case 0:
                        countColors[0]++;
                        cout<<"0 on border\n";
                        break;
                    case 1:
                        countColors[1]++;
                        cout<<"1 on border\n";
                        break;
                    case 2:
                        countColors[2]++;
                        cout<<"2 on border\n";
                        break;
                    case 3:
                        countColors[3]++;
                        cout<<"3 on border\n";
                        break;
                    case 4:
                        countColors[4]++;
                        cout<<"4 on border\n";
                        break;
                    case 5:
                        countColors[5]++;
                        cout<<"5 on border\n";
                        break;
                }
            }
        }
    }
    for(int x=0;x<6;x++) if(countColors[x]>highest) highest=countColors[x];
    for(int x=0;x<6;x++) if(countColors[x]==highest) returnMe=x;
    return returnMe;
}

//  End Function Pool ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

void Pivot(int x, int y)
{
    if(x>0)
    {
        if((grid[x-1][y]==grid[x][y])&&(isFlood[x-1][y]==false))
        {
            isFlood[x-1][y]=true;
            Pivot(x-1, y);
        }
    }
    if(x<14)
    {
        if((grid[x+1][y]==grid[x][y])&&(isFlood[x+1][y]==false))
        {
            isFlood[x+1][y]=true;
            Pivot(x+1, y);
        }
    }
    if(y>0)
    {
        if((grid[x][y-1]==grid[x][y])&&(isFlood[x][y-1]==false))
        {
            isFlood[x][y-1]=true;
            Pivot(x, y-1);
        }
    }
    if(y<14)
    {
        if((grid[x][y+1]==grid[x][y])&&(isFlood[x][y+1]==false))
        {
            isFlood[x][y+1]=true;
            Pivot(x, y+1);
        }
    }
}

void Flood(int FloodColor)
{
    for(int x=0;x<14;x++) {for (int y=0;y<14;y++) {if (isFlood[x][y]) Pivot(x,y);}} //  This run tells us what area to include in the flood
    for(int x=0;x<14;x++)
    {
        for(int y=0;y<14;y++)
        {
            if(isFlood[x][y]) grid[x][y]=FloodColor;                                                //  This floods the area
            cout<<grid[x][y]<<" ";
        }
        cout<<endl;
    }
    cout<<endl;
    for(int x=0;x<14;x++) {for (int y=0;y<14;y++) {if (isFlood[x][y]) Pivot(x,y);}} //  This updates the flood area, so we include newly acquired blocks
}

int GetColor(string s)
{
    s=s.substr(0,s.find(","));
    if(s=="237") return 0;              //  PINK == 0
    else if(s=="96") return 1;          //  PURPLE == 1
    else if(s=="243") return 2;         //  YELLOW == 2
    else if(s=="220") return 3;         //  RED == 3
    else if(s=="70") return 4;          //  BLUE == 4
    else if(s=="126") return 5;         //  GREEN == 5
    else return 6;                              
}

int main(/*int argc, char* argv[]*/)
{
    int input, counter=0;
    for(int x=0;x<14;x++) {for(int y=0;y<14;y++) {isFlood[x][y]=false;}} 
    isFlood[0][0]=true;

    //  GET INPUT
    if(file.is_open()) {while(file.good())  {getline(file, line);}}
    file.close();

    //  POPULATE GRID
    line=line.substr(11);
    for(int x=0;x<196;x++)
    {
        rgbPos=line.find("rgb");
        scPos=line.find("; \">");
        color=GetColor(line.substr(rgbPos+4,scPos-1-(rgbPos+4)));
        grid[x/14][x%14]=color;
        line=line.substr(scPos+3);
    }

    bool complete=false;
    bool floodCheck;
    while((!complete)&&(counter<25))
    {
        counter++;
        floodCheck=true;
        //cout<<"Highest border count: "<<HighestBorderCount()<<endl;
        //cin>>input;
        Flood(HighestBorderCount());
        for(int y=0;y<14;y++) {for(int z=0;z<14;z++) {if(!isFlood[y][z]) floodCheck=false;}}
        if(floodCheck) complete=true;
    }
    if(complete) {cout<<"Completed in "<<counter<<" turns!";} else {cout<<"Did not complete in 25 turns.";}
    return 0;
}
26.07.2012

  • Скорее всего, вы уже что-то испортили, и только после того, как программа начнет очистку и вызовет деструкторы, она будет распознана. 26.07.2012
  • по крайней мере, полная обратная трассировка из gdb была бы гораздо полезнее, чем только последний кадр. 26.07.2012
  • Я не знаком с gdb и нашел, как это сделать, только через Google. Что повлечет за собой полная обратная трассировка? В командной строке gdb что бы вы хотели, чтобы я набрал? 26.07.2012
  • Каково содержание Floodit.txt? 26.07.2012
  • ошибка seg исходит от libstd++, единственная часть libstd++, которую вы используете, - это файловый поток (fstream). Ваш цикл while должен проверять eof, а не хорошо. Цикл обращается к недопустимым данным в файловом потоке. также не забудьте включить ‹string›, если вы собираетесь его использовать. Всегда включайте все необходимые заголовки стандартной библиотеки. Никогда не думайте, что один заголовок будет перетаскивать другой. 26.07.2012
  • Найдена команда обратной трассировки, обновление сообщения... 26.07.2012
  • @johnathon -- я делаю file.close() через две строки после комментария //GET INPUT 26.07.2012
  • @armani, я отредактировал свой комментарий, сэр. 26.07.2012
  • FloodIt.txt содержит кучу HTML-мусора, скопированного с веб-страницы, на которой размещен Flood-It. Могу выложить, если хотите? 26.07.2012
  • По крайней мере, мы можем воспроизвести его локально. 26.07.2012
  • Ух ты, не могу поверить, что я забыл #include ‹string› -- Однако это не помогло, результаты те же. 26.07.2012
  • Упростите свой код до такой степени, чтобы мы могли его воспроизвести. Sscce.org 26.07.2012
  • Хорошо, FloodIt.txt находится по адресу pastebin.com/pUeh9xKa [все это одна строка текста] 26.07.2012
  • Обычный совет: запускайте программу под valgrind. 26.07.2012

Ответы:


1

Ошибка после завершения main указывает на проблему с уничтожением переменных в main или объектов со статической продолжительностью хранения. Если вы напечатаете обратную трассировку из отладчика, вы, по крайней мере, увидите тип объекта, который был уничтожен при возникновении ошибки.

26.07.2012
  • Немного (я не знаю платформу), но у вас гораздо больше информации. Вы можете перемещаться вверх и вниз по стеку и видеть параметры функций, и этого должно быть достаточно, чтобы понять, какой объект уничтожается. В качестве быстрой догадки единственный объект, у которого есть нетривиальный деструктор, — это ifstream, попробуйте переместить его в main, чтобы избежать возможных проблем с порядком инициализации. 26.07.2012
  • Перемещение этой части в main() не помогло. Я буду больше изучать gdb, как вы упомянули. 26.07.2012
  • И платформа g++ на 64-битной Windows 7. Не знаю, какая еще информация вам понадобится. 26.07.2012
  • Красивый; Я прошел через обратную трассировку, и одна строка торчала, это была моя инициализация строковой строки - я переместил ее в main(), и она заработала без ошибки сегментации! 26.07.2012
  • @armani: Хотя для этого сбоя нет причин (по крайней мере, очевидных для меня), обратите внимание, что наименьшее количество объектов со статической продолжительностью хранения, которое у вас есть, является лучшим. (т.е. любой ценой избегайте глобальных переменных) 26.07.2012

  • 2

    В этом коде:

    for(int x=0;x<196;x++)
    {
        rgbPos=line.find("rgb");
        scPos=line.find("; \">");
        color=GetColor(line.substr(rgbPos+4,scPos-1-(rgbPos+4)));
        grid[x/14][x%14]=color;
        line=line.substr(scPos+3);
    }
    

    Вы не проверяете, возвращает ли find npos или нет. Таким образом, у вас будет странная индексация вашего объекта string.

    Также в Pivot:

    //...
    if(x<14)
    {
        if((grid[x+1][y]==grid[x][y])&&(isFlood[x+1][y]==false))
        {
            isFlood[x+1][y]=true;
            Pivot(x+1, y);
        }
    }
    //...
    if(y<14)
    {
        if((grid[x][y+1]==grid[x][y])&&(isFlood[x][y+1]==false))
        {
            isFlood[x][y+1]=true;
            Pivot(x, y+1);
        }
    }
    

    Вы индексируете границу своего массива isFlood и присваиваете ему значение.

    26.07.2012
  • Я не думаю, что это проблема, потому что это происходит в начале моего кода main(). Я вижу, что другие операции выполняются во время работы программы, плюс у меня вчера эта программа работала с ручным вводом cin. Не уверен, что я настроил, чтобы вызвать мой текущий segfault, даже возврат к вводу cin дает мне segfault. 26.07.2012
  • Ты прав. Что на самом деле произошло, так это то, что вы переполняете свой буфер isFlood, и это портит ваш line. 26.07.2012

  • 3

    Попробуйте построить с помощью http://en.wikipedia.org/wiki/Valgrind.

    26.07.2012
  • @armani, если вы используете Windows, свяжите с MFC и используйте DEBUG_NEW. 26.07.2012
  • Наверное, это слишком сложно для меня. Не знаю, что это такое, и гугление меня смутило. 26.07.2012
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..