在没有调试器的情况下运行时睡眠会导致问题

时间:2021-02-22 21:28:08

标签: c++ algorithm sleep freeze glut

我正在制作一个小项目,逐步展示不同排序算法的工作原理。本质上只是一堆用 opengl 绘制的随机线,然后进行排序。为了显示我的步骤,在算法中的每次交换之后,我重绘屏幕并使程序休眠大约 5 毫秒。当使用调试器在 Visual Studio 中运行时,根本没有问题,但如果我在没有调试器的情况下运行,无论是使用 ctrl+f5 还是从 Windows 资源管理器中,显示都会冻结并停止在排序算法中途停止绘制(不管什么算法)——但是,控制台仍然会在最后输出信息(比较和交换的次数),并且根据需要多长时间,延迟确实仍然有效)。我已经缩小范围是因为睡眠功能,因为当我不使用睡眠时,它可以完美地工作,只是太快了。为了让事情变得更奇怪,我将 exe 发送给了一个朋友,对他来说没有问题。我还尝试将 _NO_DEBUG_HEAP 设置为 1 以查看是否可以在附加调试器的情况下捕获错误,但没有成功。

如果 Windows.h Sleep(x) 有一些奇怪的地方,我使用 ctime clock 类型/函数创建了自己的小函数,但仍然很奇怪,没有调试器错误继续存在。

我自己的睡眠功能:

void slp(clock_t wait)
{
    clock_t goal;
    goal = wait + clock();
    while(goal > clock());
}

有什么可以解释为什么这对一个人(我的朋友)而不是我自己有效?下面包含了更多代码,尽管我不认为其中任何一个是问题,但我认为这只是我需要一种更好的方式来睡眠/延迟程序。

/*My window creation/drawing code, just in case its a glut issue some how
(normally I'd use glfw but couldn't get things like glRecti to work for the life of me)*/

constexpr int N = 320;
int heights[ N ];

void gfx();

int main(int argc, char** argv)
{
    for (int i = 0; i < N; i++)
    {
        heights[ i ] = rand() % 600;
    }

    glutInit(&argc, argv);
    glutInitWindowSize(1280, 720);
    int cx = (glutGet(GLUT_SCREEN_WIDTH) - 1280) / 2;
    int cy = (glutGet(GLUT_SCREEN_HEIGHT) - 720) / 2;
    glutInitWindowPosition(cx, cy);
    glutCreateWindow("Sorting Visualizer");
    glutDisplayFunc(gfx);
    glClearColor(0, 0, 0, 1);
    gluOrtho2D(0, 1280, 0, 720);
    glutMainLoop();
    return 0;
}

gfx 函数很简单

void gfx()
{
    glClear(GL_COLOR_BUFFER_BIT);
    HeapSorter<int, N> heap(heights);
    heap.sort();
    heap.printInfo();
}

现在是排序算法:

template <typename T, int N>
class HeapSorter : public Sorter<T, N>
{
    using Sorter<T, N>::drawStep;
    using Sorter<T, N>::mSwaps;
    using Sorter<T, N>::mCompares;
    using Sorter<T, N>::mArr;
    using Sorter<T, N>::mName;
public:
    HeapSorter(T arr[ N ], int slp = 5) : Sorter<T, N>("Heap Sort", arr, slp) {}

    void sort()
    {
        for (int i = N / 2 - 1; i >= 0; i--)
        {
            heapify(N, i);
        }


        for (int i = N - 1; i > 0; i--)
        {
            std::swap(mArr[ 0 ], mArr[ i ]);
            mSwaps++;
            drawStep();
            heapify(i, 0);
        }
    }

private:
    void heapify(const int n, int i)
    {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;

        ++mCompares;
        if (left < n && mArr[ left ] > mArr[ largest ])
        {
            largest = left;
        }

        ++mCompares;
        if (right < n && mArr[ right ] > mArr[ largest ])
        {
            largest = right;
        }

        if (largest != i)
        {
            std::swap(mArr[ i ], mArr[ largest ]);
            ++mSwaps;
            drawStep();
            heapify(n, largest);
        }
    }
};

超类只处理绘图,sleep函数发生在drawStep

template <typename T, int N>
class Sorter
{
public:
    Sorter(std::string name, T arr[ N ], const int slp = 5) :
        mName(std::move(name)),
        mSleep(slp)
    {
        for (auto i = 0; i < N; i++)
        {
            mArr[ i ] = arr[ i ];
        }
    }

    void printInfo() const
    {
        std::cout << mName << " - Compares: " << mCompares << " - Swaps: " << mSwaps << "\n";
    }

protected:


    static void drawText(const float x, const float y, const std::string& txt)
    {
        glColor3f(1, 1, 1);
        glRasterPos2f(x, y);

        for (auto i : txt)
        {
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, i);
        }
    }

    void drawStep()
    {
        glClear(GL_COLOR_BUFFER_BIT);

        drawText(5, 700, mName);
        drawText(5, 680, "Compares: " + std::to_string(mCompares));
        drawText(5, 660, "Swaps: " + std::to_string(mSwaps));
        drawText(5, 640, "Sleep: " + std::to_string(mSleep) + " ms");

        glColor3f(1.f, 0.f, 0.f);

        for (auto i = 0; i < N; i++)
        {
            glRecti(4 * i, 100, 4 * i + 3, 100 + mArr[ i ]);
        }

        glFlush();
        SLP(mSleep);
    }

    std::string mName;
    int mSleep;
    int mCompares = 0;
    int mSwaps = 0;

    T mArr[ N ];
};

SLP 只是一个宏,因此我可以快速测试不同的睡眠功能,而无需更改我可能使用它的任何地方

0 个答案:

没有答案