我遇到的问题是,当我想分配缓冲区数组值时,会出现分段错误 代码:
#define BMPHEADER_SIZE 54
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
// there will be a low level I/O function from the operating system
extern long write(int, const char *, unsigned long);
float zoom = 1.5;
float quadLimit = 3.0;
char colorLimit = 40;
pthread_mutex_t lock;
typedef struct Complex_s {
float re;
float im;
} Complex;
typedef struct {
int width;
int height;
int anfang;
int ende;
float imageRelation;
char *blueGreenRed;
//char *buffer;
char ***buffer;
}info1;
// bad, but fast !!!
int intFloor(double x) {
return (int)(x+100000) - 100000;
}
// count chars until \0 or space or "to long"
int len(char * str) {
int ddorf=0;
while (str[ddorf] != '\0' && str[ddorf] != ' ' && ddorf != 40225) ++ddorf;
return ddorf;
}
// read a positive number from a char array
int str2num(char * str) {
int result = 0;
int b = 1;
int l = len(str);
int i;
for(i=1; i<l; ++i) b *= 10;
for(i=0; i<l; ++i) {
result += b * (int)(str[i] - '0');
b /= 10;
}
return result;
}
void toRGB(int id, char * blueGreenRed) {
blueGreenRed[0] = 0;
blueGreenRed[1] = 0;
blueGreenRed[2] = 0;
if ( id == colorLimit ) return;
float hi,q,t,coeff;
coeff = 7.0 * (id/(float)colorLimit);
hi = intFloor(coeff);
t = coeff - hi;
q = 1 - t;
if (hi == 0.0) {
blueGreenRed[2] = 0;
blueGreenRed[1] = t*255; //immer mehr green und blau -> dunkelblau zu cyan
blueGreenRed[0] = t*127 + 128;
} else if (hi == 1.0) {
blueGreenRed[2] = t*255; //immer mehr rot -> cyan zu weiss
blueGreenRed[1] = 255;
blueGreenRed[0] = 255;
} else if (hi == 2.0) {
blueGreenRed[2] = 255;
blueGreenRed[1] = 255;
blueGreenRed[0] = q*255; // immer weniger blau -> weiss zu gelb
} else if (hi == 3.0) {
blueGreenRed[2] = 255;
blueGreenRed[1] = q*127 + 128; // immer weniger green -> gelb zu orange
blueGreenRed[0] = 0;
} else if (hi == 4.0) {
blueGreenRed[2] = q*127 + 128; // orange wird dunkler -> orange zu braun
blueGreenRed[1] = q*63 + 64;
blueGreenRed[0] = 0;
} else if (hi == 5.0) {
blueGreenRed[2] = 128;
blueGreenRed[1] = 64;
blueGreenRed[0] = t*128; // mehr blau -> braun zu violett
} else if (hi == 6.0) {
blueGreenRed[2] = q*128; // weniger rot und green -> violett wird dunkelblau
blueGreenRed[1] = q*64;
blueGreenRed[0] = 128;
}
}
char* calculatePunkt(int x, int y, int width, int height, float imageRelation, char *blueGreenRed) {
char iterate=0;
Complex c = {0,0};
Complex newz = {0,0};
Complex z = {0,0};
float quad=0;
c.re = zoom * (-1.0 + imageRelation * ( (x-1.0) / (width-1.0)) );
c.im = zoom * ( 0.5 - (y-1.0) / (height-1.0) );
// iterate
for ( iterate=1; iterate < colorLimit && quad < quadLimit; ++iterate ) {
quad = z.re * z.re + z.im * z.im;
newz.re = (z.re * z.re) - (z.im * z.im) + c.re;
newz.im = z.re * z.im * 2.0 + c.im;
z = newz;
}
toRGB(iterate, blueGreenRed);
return blueGreenRed;
}
void *calculateThread(void *arg){
info1 *abc =(info1*) arg;
int x, y;
int anfang = abc->anfang;
int ende = abc->ende;
int width = abc->width;
int height = abc->height;
float imageRelation = abc->imageRelation;
char *blueGreenRed = abc->blueGreenRed;
char ***buffer = abc->buffer;
//char *buffer = abc->buffer;
for (y=anfang; y <= ende; ++y) {
for (x=1; x <= width; ++x) {
char* rgb = calculatePunkt(x, y, width, height, imageRelation, blueGreenRed);
fprintf(stderr, "test, %d\n", anfang);
pthread_mutex_lock(&lock);
//buffer[(y-1)+(height*(x-1))+(height*width*0)] = rgb[0];
//buffer[(y-1)+(height*(x-1))+(height*width*1)] = rgb[1];
//buffer[(y-1)+(height*(x-1))+(height*width*2)] = rgb[2];
buffer[y-1][x-1][0] = 1;
buffer[y-1][x-1][1] = 1;
buffer[y-1][x-1][2] = 1;
pthread_mutex_unlock(&lock);
}
}
}
int main(int argc, char ** argv, char ** envp) {
int width = str2num(argv[1]);
int height = str2num(argv[2]);
int anzahl_threads = str2num(argv[3]);
float imageRelation = (float)width/(float)height;
int i, j, anfang, ende, y;
char blueGreenRed[3];
char buffer[height][width][3];
for(i=0; i<height; i++){
for(j=0; j<width; j++){
buffer[i][j][0]=0;
buffer[i][j][1]=0;
buffer[i][j][2]=0;
}
}
//char *buffer = malloc(height*width*3*sizeof(char));
//*buffer = (char*){ 0 };
unsigned char info[BMPHEADER_SIZE] = {
//size
'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0,
//width //height
40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0,
// datasize
0,0,0,0, 0,0,0,0
};
// BMP lines must be of lengths divisible by 4
char span[4] = "\0\0\0\0";
int spanBytes = 4 - ((width * 3) % 4);
if (spanBytes == 4) spanBytes = 0;
int psize = ((width * 3) + spanBytes) * height;
*( (int*) &info[2]) = BMPHEADER_SIZE + psize;
*( (int*) &info[18]) = width;
*( (int*) &info[22]) = height;
*( (int*) &info[34]) = psize;
write(1, (char *) info, BMPHEADER_SIZE);
struct timeval start, end;
gettimeofday(&start, 0);
int interval = height/anzahl_threads;
info1 *abc = malloc(anzahl_threads*sizeof(info1));;
pthread_t *thread = malloc(anzahl_threads*sizeof(pthread_t));
if(pthread_mutex_init(&lock, NULL)){
fprintf(stderr, "Error initializing mutex\n");
return 1;
}
for(i=0; i<anzahl_threads; i++){
(abc+i)->width = width;
(abc+i)->height = height;
(abc+i)->imageRelation = imageRelation;
(abc+i)->blueGreenRed = blueGreenRed;
(abc+i)->buffer = ***buffer;
//abc->buffer = *buffer;
anfang = 1+(i*interval);
(abc+i)->anfang = anfang;
if(i<(anzahl_threads-1)){
ende = (i*interval)+interval;
}
else{
ende = height;
}
(abc+i)->ende = ende;
if (pthread_create(&thread[i], NULL, calculateThread, (void*)(abc+i))) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
}
for(i=0; i<anzahl_threads; i++){
if (pthread_join(thread[i], NULL)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
}
pthread_mutex_destroy(&lock);
for(y=1; y<=height; ++y){
// BMP lines must be of lengths divisible by 4
write(1, span, spanBytes);
}
write(1, buffer, height*width*3);
//free(buffer);
free(thread);
free(abc);
gettimeofday(&end, 0);
unsigned long timediff = ((end.tv_sec*1000000)+end.tv_usec) - ((start.tv_sec*1000000)+start.tv_usec);
fprintf(stderr, "Gesamtzeit in Mikrosek.: %lu\n", timediff);
return 0;
}
Valgrind的:
==28366== Thread 2:
==28366== Invalid read of size 8
==28366== at 0x401115: calculateThread (in /home/nilskk/Schreibtisch/Betriebssysteme/Abgabe2/Aufgabe1/mandel1)
==28366== by 0x4E3F183: start_thread (pthread_create.c:312)
==28366== by 0x514F37C: clone (clone.S:111)
==28366== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==28366==
==28366==
==28366== Process terminating with default action of signal 11 (SIGSEGV)
==28366== Access not within mapped region at address 0x0
==28366== at 0x401115: calculateThread (in /home/nilskk/Schreibtisch/Betriebssysteme/Abgabe2/Aufgabe1/mandel1)
==28366== by 0x4E3F183: start_thread (pthread_create.c:312)
==28366== by 0x514F37C: clone (clone.S:111)
==28366== If you believe this happened as a result of a stack
==28366== overflow in your program's main thread (unlikely but
==28366== possible), you can try to increase the size of the
==28366== main thread stack using the --main-stacksize= flag.
==28366== The main thread stack size used in this run was 8388608.
--28366-- REDIR: 0x50d7d00 (libc.so.6:free) redirected to 0x4c2bd80 (free)
==28366==
==28366== HEAP SUMMARY:
==28366== in use at exit: 640 bytes in 4 blocks
==28366== total heap usage: 4 allocs, 0 frees, 640 bytes allocated
==28366==
==28366== Searching for pointers to 4 not-freed blocks
==28366== Checked 16,869,264 bytes
==28366==
==28366== Thread 1:
==28366== 544 bytes in 2 blocks are possibly lost in loss record 3 of 3
==28366== at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28366== by 0x4012E14: allocate_dtv (dl-tls.c:296)
==28366== by 0x4012E14: _dl_allocate_tls (dl-tls.c:460)
==28366== by 0x4E3FD92: allocate_stack (allocatestack.c:589)
==28366== by 0x4E3FD92: pthread_create@@GLIBC_2.2.5 (pthread_create.c:500)
==28366== by 0x40187E: main (in /home/nilskk/Schreibtisch/Betriebssysteme/Abgabe2/Aufgabe1/mandel1)
==28366==
==28366== LEAK SUMMARY:
==28366== definitely lost: 0 bytes in 0 blocks
==28366== indirectly lost: 0 bytes in 0 blocks
==28366== possibly lost: 544 bytes in 2 blocks
==28366== still reachable: 96 bytes in 2 blocks
==28366== suppressed: 0 bytes in 0 blocks
==28366== Reachable blocks (those to which a pointer was found) are not shown.
==28366== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==28366==
==28366== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==28366==
==28366== 1 errors in context 1 of 2:
==28366== Thread 2:
==28366== Invalid read of size 8
==28366== at 0x401115: calculateThread (in /home/nilskk/Schreibtisch/Betriebssysteme/Abgabe2/Aufgabe1/mandel1)
==28366== by 0x4E3F183: start_thread (pthread_create.c:312)
==28366== by 0x514F37C: clone (clone.S:111)
==28366== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==28366==
==28366== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
当我在线程函数中注释缓冲区赋值时,它可以工作。所以它必须对缓冲区做一些事情,但我没有看到错误。
答案 0 :(得分:1)
这行代码显然是错误的。左侧的类型为char ***
,您为其分配char
,特别是0
的值,因为这是您初始化buffer
的方式在main
(abc+i)->buffer = ***buffer;
理想情况下,你希望它是
(abc+i)->buffer = buffer;
但由于buffer
不是{3}而是char ***
,因此它不会起作用。
您可以通过分配各个级别来创建buffer
作为char ***
,或者因为每个线程只访问buffer
的子集,您可以将其设为全局变量吗?
答案 1 :(得分:1)
您正尝试通过指向char
(char ***
)指针的指针来访问数据,但数据实际上是数组[{{{height
]的数组1 {}} width
(char
)的数组[3]。指向此数组的第一个元素的指针是指向char [height][width][3]
(width
)的数组[3]的数组[char
]的指针。由于char (*)[width][3]
和width
是可变的,height
类型不能包含info1
类型的成员buffer
,因此最简单的做法是将其声明为char (*)[width][3]
:
void *
在函数typedef struct {
...
void *buffer;
...
} info1;
中,原始calculateThread
值可用,因此您可以使用正确的类型声明局部变量width
并初始化它:
buffer
在功能 char (*buffer)[width][3] = abc->buffer;
中,作业main
显然不正确,因为(abc+i)->buffer = ***buffer;
的类型为***buffer
。你想要一个指向缓冲区内容开头的指针,它只是char
,所以把它改为:
buffer