c ++ - 多线程中的内存问题

问题描述 投票:-2回答:1

我目前在uni学习c ++中的线程,我有一个涉及ncurses的小项目 - 弹跳球。我希望球能够产生,直到我按'x'。按下按钮后,它会退出,但它也会显示有关内存保护违规的信息。

当我使用gdb时,按'x'后,它说:

线程1“p”接收信号SIGSEGV,分段故障。 malloc.c中的_int_malloc(av = av @ entry = 0x7ffff71c2c40,bytes = bytes @ entry = 28)中的0x00007ffff6e6b3c1:3612

问题可能出在for循环中,但我不确定。

我写的代码是:

#include "window.h"
#include <stdlib.h>
#include <time.h>
#include <thread>
#include <unistd.h>
#include <ncurses.h>
#include <atomic>

Window *window;
std::atomic<bool> run(true);


void exit() {
    while(run) {
        char z = getch();
        if(z == 'q') run = false;
    }
}

void ballFunction(int a) {
    int nr = a;
    while (run && window->balls[nr]->counter < 5) {
        usleep(50000);
        window->balls[nr]->updateBall();
    }
    window->balls[nr]->x = -1;
    window->balls[nr]->y = -1;
} 

void updateWindow2() {
    while(run) {
        usleep(50000);
        window->updateWindow();
    }
    delete window;
}

int main() {
    srand(time(NULL));

    window = new Window();

    int i = 0;

    std::vector<std::thread> threads;

    std::thread threadWindow(updateWindow2);
    std::thread threadExit(exit);

    while(run = true) {
         window->addBall();
         threads.push_back(std::thread(ballFunction, i));
         i++;
         sleep(1);
    }

    threadWindow.join();
    threadExit.join();

    for(int j=2; j<i+2; j++) {
        threads[j].join();
    }

    return 0;
    }

#include "window.h"
#include <ncurses.h>
#include <unistd.h>

Window::Window()
{
    initWindow();
}

Window::~Window()
{
    endwin(); 
}

void Window::initWindow()
{
    initscr();
    noecho();
    curs_set(FALSE); 
    clear();
    refresh();
}

void Window::addBall()
{
    Ball *ball = new Ball(this->ballCounter++);
    this->balls.push_back(ball);
}

void Window::updateWindow()
{
    for(int i = 0; i<ballCounter; i++)
    {
        if(balls[i]->update())
        {
            clear(balls[i]->yy, 
                balls[i]->xx);
            drawBall(balls[i]->y,
                 balls[i]->x);
        }
    }
    refresh();
}

void Window::clear(int y, int x)
{
    mvprintw(y, x, " ");
}

void Window::drawBall(int y, int x)
{
    mvprintw(y, x, "o"); 
}
c++ multithreading ncurses
1个回答
0
投票

问题是你有一个线程添加到balls向量,而其他线程正在读取它。

addBall调用push_back时,如果向量容量不够大,将分配新内存,将现有对象移动或复制到新块,并释放旧内存。发生这种情况时,运行ballFunction的线程可以写入不再分配的内存。这会导致未定义的行为,包括您遇到的分段错误。

您需要使用某种形式的互斥,或确保balls向量分配了足够的空间(使用balls.reserve(more_elements_than_youll_ever_create))。

在一个不相关的注释中,你的主要while循环永远不会终止,因为你有一个赋值而不是比较作为条件(使用while (run)while (run == true))。

© www.soinside.com 2019 - 2024. All rights reserved.