简体   繁体   English

并行mandelbrot算法中C语言中的memcpy的分段错误:如何在结构中使用指针?

[英]Segmentation fault with memcpy in C in parallel mandelbrot algorithm: How to use pointers in a struct?

The goal is to write a parallelization out of a sequential mandelbrot algorithm. 目标是从顺序mandelbrot算法中编写并行化。 I'm having some problems with my the data types and pointers. 我的数据类型和指针有问题。

This is how my main.c looks like: 这是我的main.c的样子:

int main(int argc, char **argv)
{
    /****
    Here are initializations and some for my question irrelevant code...
    *****/

    unsigned char (*image)[x_resolution][3];
    image = malloc(x_resolution * y_resolution * sizeof(char[3]));

    // compute mandelbrot   
    mandelbrot_draw(x_resolution, y_resolution, max_iter, view_x0, view_x1,
    view_y0, view_y1, x_stepsize, y_stepsize, palette_shift, image, 
    num_threads);

    free(image);
}

The first thing that I'm struggling with, is the line unsigned char (*image)[x_resolution][3]; 我苦苦挣扎的第一件事是unsigned char (*image)[x_resolution][3];unsigned char (*image)[x_resolution][3]; The way I understand it, is that I'm creating a pointer with *image . 我的理解方式是,我正在使用*image创建一个指针。 I also know the use of brackets from dealing with arrays. 我也知道使用括号处理数组。 But I do not really understand what data type I get with this. 但是我真的不明白我能得到什么数据类型。

Then my parallel algorithm starts like this: 然后我的并行算法就这样开始:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <complex.h>
#include <pthread.h>
#include "mandelbrot.h"

struct pthread_args_struct
{
    int x_resolution;
    int y_resolution_lower_boundary;
    int y_resolution_upper_boundary;
    int max_iter;
    double view_x0;
    double view_y1;
    double x_stepsize;
    double y_stepsize;
    int palette_shift;

    unsigned char** img;
};

I need this struct because I need to pass arguments to pthreads_create, and this function can only get one argument for input. 我需要此结构,因为我需要将参数传递给pthreads_create,并且此函数只能获取一个参数作为输入。 I researched how you can deal with a pointer inside a struct and did it like suggested here: Storing and Accessing a 2D Array in a Struct 我研究了如何处理结构内部的指针,并按照此处的建议进行了处理: 在结构中存储和访问2D数组

I also have the following to functions in my code: 我的代码中还具有以下功能:

void mandelbrot_draw(int x_resolution, int y_resolution, int max_iter,
                double view_x0, double view_x1, double view_y0, double 
                view_y1, double x_stepsize, double y_stepsize,
                int palette_shift, unsigned char (*img)[x_resolution][3],
                int num_threads) {

    //I split the image into rows 
    //  and let each thread calculate the pixels for one row
    int y_resolution_thread[num_threads+1]; 
    for (int t = 0; t < num_threads; t++)
    {       
        y_resolution_thread[t] = t*(y_resolution/num_threads);
        y_resolution_thread[num_threads] = y_resolution;
    }

    //allocate pthreads space and space for struct
    pthread_t *threads = (pthread_t*) malloc (num_threads*sizeof(pthread_t));
    struct pthread_args_struct* args = (struct pthread_args_struct*) malloc 
    (num_threads*sizeof(struct pthread_args_struct));

    //create threads, start mandelbrot_draw_row in parallel
    for(int i = 0; i < num_threads; ++i) {
        args[i].y_resolution_lower_boundary = y_resolution_thread[i];
        args[i].y_resolution_upper_boundary = y_resolution_thread[i+1];         
        args[i].x_resolution = x_resolution;
        args[i].max_iter = max_iter;
        args[i].view_x0 = view_x0;
        args[i].view_y1 = view_y1;
        args[i].x_stepsize = x_stepsize;
        args[i].y_stepsize = y_stepsize;
        args[i].palette_shift = palette_shift;

        memcpy(&args[i].img, img, sizeof(img));

        //create thread and pass arguments
        pthread_create (&threads[i] , NULL, mandelbrot_draw_row, args+i);
    }

    //wait for finish and join
    for (int i = 0; i < num_threads; ++i){
        pthread_join(threads[i], (void*)&img);
    }

    free(threads); free(args);
    return((void*) &img);
}

void* mandelbrot_draw_row (void* args){

    struct pthread_args_struct* arg = (struct pthread_args_struct*) args;
    arg->img = malloc(sizeof(arg->img));

    int k;

    for (int i = arg->y_resolution_lower_boundary; i < arg-> 
    y_resolution_upper_boundary; i++)
    {
        for (int j = 0; j < arg->x_resolution; j++)
        {
            k = 0;
            //do some calculations here

            if (k == arg->max_iter)
            {   
                memcpy(&args->img[i][j], "\0\0\0", 3); <- here I get a 
                                                         segmentation fault
            }
            else
            {
                int index = (k + arg->palette_shift)
                        % (sizeof(colors) / sizeof(colors[0])); 
                memcpy(&args->img[i][j], colors[index], 3);
            }
        }
    }
    return(void*) &arg->img;
}

And here comes my main problem: I get a segmentation fault in memcpy(&args->img[i][j], "\\0\\0\\0", 3); 这是我的主要问题:我在memcpy(&args->img[i][j], "\\0\\0\\0", 3);遇到分段错误memcpy(&args->img[i][j], "\\0\\0\\0", 3); . I think I'm doing something really wrong here with the pointers, but I cannot really understand what I'm supposed to do. 我认为我在用指针做错了什么,但是我真的不明白我该怎么做。

Your problem is that your image-pointer is pointing to a single, big 3D array. 您的问题是图像指针指向单个大型3D阵列。 It's a whole bunch of values right next to each other in memory. 这是一堆在内存中彼此相邻的值。 I've tried to draw a picture to represent a 3D array below. 我试图绘制一张图片来表示下面的3D数组。

But then you're trying to use it like a 1D array of pointers to 1D arrays. 但是,然后您试图像使用指向1D数组的1D数组那样使用它。 Whichever way you slice it, this won't possibly work because your array doesn't have pointers in it to begin with. 无论您以哪种方式对其进行切片,这都将无法工作,因为您的数组中没有指针。

You should change the type: 您应该更改类型:

unsigned char** img;

so that it matches the one in main : 这样它就匹配main中的一个:

unsigned char (*image)[x_resolution][3];

And then replace this: 然后替换为:

memcpy(&args[i].img, img, sizeof(img));

with just: 只是:

args[i].img = img;

I see you were using memcpy because the compiler complained you were trying to assign a pointer to a different type of pointer. 我看到您使用memcpy是因为编译器抱怨您试图将一个指针分配给其他类型的指针。 The compiler complained for a reason. 编译器抱怨是有原因的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM