很奇怪的问题-C&并行线程

发布于 2024-11-07 03:53:31 字数 5409 浏览 0 评论 0原文

我对这段代码遇到了一个非常奇怪的问题,抱歉它非常混乱。基本上它是一个 pagerank 算法。每个结构体网页都包含在动态数组“pages”中。页面向量通过算法,直到其绝对值 (|P|) 小于“epsilon”。现在问题出在第 195-201 行。如果我删除这些行中数组的迭代(即空 while 循环),它适用于只需要一次迭代的情况。但是,当我确实有 for 循环(即使对于一次迭代情况)时,它会抛出 error6 (第 179 行,调试显示 e == NULL),甚至没有运行插入的循环。我已经设置了断点等,但仍然给出了 error6,甚至没有阅读额外的代码。这是怎么回事?我对 C 和并行编程还很陌生,所以它可能是一些基础知识。将不胜感激任何帮助!

输入格式:

number_of_cores
number_of_pages
...
page_names
...
page_links

输出格式:

...
page_rank
...

代码

#include <assert.h>
#include <math.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const double D = 0.85;
static const double EPSILON = 0.005;
int ncores;
int npages;
struct webpage** pages;
int maxdepth;

struct webpage* has(char s[20], int e);
void* threadf(void* ptr);
int quit(void);
double rec(int s, int f, int depth);




struct webpage {
    char name[20];
    double oldrank;
    double rank;
    struct node* in;
    int incount;
    int outcount;

};

struct node {
    struct webpage* data;
    struct node* next;
};

struct arg {
    int s;
    int f;
    int depth;
    double ret;
};

struct webpage*
has(char s[20], int e) {
    int p;
    for (p=0; p<e; ++p) {
        if (strcmp(s, pages[p]->name) == 0) {
            return pages[p];
        }
    }
    return NULL;
}

void *
threadf(void* ptr) {
    struct arg* curr = (struct arg*)ptr;
    curr->ret = rec(curr->s, curr->f, curr->depth);
}
int
quit(void) {
    int i;
    for(i=0; i<npages; ++i) {
        struct node* curr = pages[i]->in;
        struct node* next;
        while(curr != NULL) {
            next = curr->next;
            free(curr);
            curr = next;
        }
        free(pages[i]);
    }
    free(pages);
    return 0;
}

double 
seq(int s, int f) {
    double sum;
    sum = 0;
    int w;
    for (w=s; w<=f; w++) {
        struct webpage* curr = pages[w];
        double ser;
        ser = 0;
        struct node* currn = curr->in;
        while (currn != NULL) {
            struct webpage* n = currn->data;
            ser = ser + ((n->oldrank)/(n->outcount));
            currn = currn->next;
        }

        double temp = (((1-D)/npages) + (D*ser)); 
        sum = sum + pow((temp - curr->oldrank), 2);
        curr->oldrank = curr->rank;
        curr->rank = temp;
    }
    return sum;
}


double 
rec(int s, int f, int depth) {
    if (depth == maxdepth ) {
        return seq(s, f);
    } else {
        if (s < f){
            int m;
            m = (s+f)/2;
            struct arg l;
            struct arg r;
            l.s = s;
            l.f = m;
            l.depth = depth+1;
            r.s = m+1;
            r.f = f;
            r.depth = depth+1;
            pthread_t left, right;
            pthread_create(&left, NULL, threadf, (void*) &l);
            pthread_create(&right, NULL, threadf, (void*) &r);
            pthread_join(left, NULL);
            pthread_join(right, NULL);
            double res;
            res = l.ret + r.ret;
            return res;
        } 
        return seq(s, f);

    }
}

int
main(void) {
    if (scanf("%d", &ncores) != 1) {
        printf("error1\n");
        return quit();
    }
    if (scanf(" %d", &npages) != 1) {
        printf("error2\n");
        return quit();
    }
    int i;
    char n[20];
    pages = (struct webpage**)malloc(npages*sizeof(struct webpage*));
    for (i=0; i<npages; ++i) {

        if (scanf(" %c", n) != 1 || has(n, i) != NULL) {
            printf("error3\n");
            return quit();
        }
        pages[i] = (struct webpage*)malloc(sizeof(struct webpage));
        struct webpage* curr = pages[i];
        strcpy(curr->name, n);
        curr->oldrank = 1/npages;
        curr->in = NULL;
        curr->incount = 0;
        curr->outcount = 0;

    }

    int nedges;
    if (scanf(" %d", &nedges) != 1) {
        printf("error4\n");
        return quit();
    }
    for (i=0; i<nedges; ++i) {
        char f[20], t[20];
        if (scanf(" %s %s", f, t) != 2) {
            printf("error5\n"); 
            return quit();
        }
        char from[20], to[20];
        strcpy(from, f);
        strcpy(to, t);
        struct webpage* s = has(from, npages);
        struct webpage* e = has(to, npages);
        if (s == NULL || e == NULL) {
            printf("error6\n");
            return quit();
        }
        s->outcount++;
        e->incount++;
        struct node* new;
        new = (struct node*)malloc(sizeof(struct node));
        new->data = s;
        if (e->in == NULL) {
            e->in = new;
        } else {
            new->next = e->in;
            e->in = new;
        }
    }
    maxdepth = (log(ncores))/(log(2)) + 0.5;
    while (sqrt(rec(0, npages-1, 0)) > EPSILON){
        int c;
        for (c=0; c<npages; ++c) {
            struct webpage* curr = pages[c];
            curr->oldrank = curr->rank;
        }
    }
    int z;
    for (z=0; z<npages; ++z) {
        struct webpage* curr = pages[z];
        printf("%s %.4lf\n", curr->name, curr->rank);
    }

    return quit();

}

示例 输入:

8
4
a
b
c
d
4
a a

输出:

error6

I'm having a very strange problem with this bit of code, sorry its pretty messy. Basically its a pagerank algorithm. Each struct webpage is contained in the dynamic array "pages". The pages vector is put through the algorithm until its absolute value (|P|) is smaller than 'epsilon'. Now the issue is with lines 195-201. If i remove the iteration over the array in those lines (i.e. an empty while loop), it works for cases that only require one iteration. However, when i do have the for loop (even for one iteration cases), it throws error6 (line 179, debugging shows e == NULL) without even having run over the inserted loop. Ive set breakpoints etc, and still gives error6 without even having read the extra code. What's going on here? Im pretty new to C and parallel programming so its probably something fundamental. Would appreciate any help!

input format:

number_of_cores
number_of_pages
...
page_names
...
page_links

output format:

...
page_rank
...

code

#include <assert.h>
#include <math.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const double D = 0.85;
static const double EPSILON = 0.005;
int ncores;
int npages;
struct webpage** pages;
int maxdepth;

struct webpage* has(char s[20], int e);
void* threadf(void* ptr);
int quit(void);
double rec(int s, int f, int depth);




struct webpage {
    char name[20];
    double oldrank;
    double rank;
    struct node* in;
    int incount;
    int outcount;

};

struct node {
    struct webpage* data;
    struct node* next;
};

struct arg {
    int s;
    int f;
    int depth;
    double ret;
};

struct webpage*
has(char s[20], int e) {
    int p;
    for (p=0; p<e; ++p) {
        if (strcmp(s, pages[p]->name) == 0) {
            return pages[p];
        }
    }
    return NULL;
}

void *
threadf(void* ptr) {
    struct arg* curr = (struct arg*)ptr;
    curr->ret = rec(curr->s, curr->f, curr->depth);
}
int
quit(void) {
    int i;
    for(i=0; i<npages; ++i) {
        struct node* curr = pages[i]->in;
        struct node* next;
        while(curr != NULL) {
            next = curr->next;
            free(curr);
            curr = next;
        }
        free(pages[i]);
    }
    free(pages);
    return 0;
}

double 
seq(int s, int f) {
    double sum;
    sum = 0;
    int w;
    for (w=s; w<=f; w++) {
        struct webpage* curr = pages[w];
        double ser;
        ser = 0;
        struct node* currn = curr->in;
        while (currn != NULL) {
            struct webpage* n = currn->data;
            ser = ser + ((n->oldrank)/(n->outcount));
            currn = currn->next;
        }

        double temp = (((1-D)/npages) + (D*ser)); 
        sum = sum + pow((temp - curr->oldrank), 2);
        curr->oldrank = curr->rank;
        curr->rank = temp;
    }
    return sum;
}


double 
rec(int s, int f, int depth) {
    if (depth == maxdepth ) {
        return seq(s, f);
    } else {
        if (s < f){
            int m;
            m = (s+f)/2;
            struct arg l;
            struct arg r;
            l.s = s;
            l.f = m;
            l.depth = depth+1;
            r.s = m+1;
            r.f = f;
            r.depth = depth+1;
            pthread_t left, right;
            pthread_create(&left, NULL, threadf, (void*) &l);
            pthread_create(&right, NULL, threadf, (void*) &r);
            pthread_join(left, NULL);
            pthread_join(right, NULL);
            double res;
            res = l.ret + r.ret;
            return res;
        } 
        return seq(s, f);

    }
}

int
main(void) {
    if (scanf("%d", &ncores) != 1) {
        printf("error1\n");
        return quit();
    }
    if (scanf(" %d", &npages) != 1) {
        printf("error2\n");
        return quit();
    }
    int i;
    char n[20];
    pages = (struct webpage**)malloc(npages*sizeof(struct webpage*));
    for (i=0; i<npages; ++i) {

        if (scanf(" %c", n) != 1 || has(n, i) != NULL) {
            printf("error3\n");
            return quit();
        }
        pages[i] = (struct webpage*)malloc(sizeof(struct webpage));
        struct webpage* curr = pages[i];
        strcpy(curr->name, n);
        curr->oldrank = 1/npages;
        curr->in = NULL;
        curr->incount = 0;
        curr->outcount = 0;

    }

    int nedges;
    if (scanf(" %d", &nedges) != 1) {
        printf("error4\n");
        return quit();
    }
    for (i=0; i<nedges; ++i) {
        char f[20], t[20];
        if (scanf(" %s %s", f, t) != 2) {
            printf("error5\n"); 
            return quit();
        }
        char from[20], to[20];
        strcpy(from, f);
        strcpy(to, t);
        struct webpage* s = has(from, npages);
        struct webpage* e = has(to, npages);
        if (s == NULL || e == NULL) {
            printf("error6\n");
            return quit();
        }
        s->outcount++;
        e->incount++;
        struct node* new;
        new = (struct node*)malloc(sizeof(struct node));
        new->data = s;
        if (e->in == NULL) {
            e->in = new;
        } else {
            new->next = e->in;
            e->in = new;
        }
    }
    maxdepth = (log(ncores))/(log(2)) + 0.5;
    while (sqrt(rec(0, npages-1, 0)) > EPSILON){
        int c;
        for (c=0; c<npages; ++c) {
            struct webpage* curr = pages[c];
            curr->oldrank = curr->rank;
        }
    }
    int z;
    for (z=0; z<npages; ++z) {
        struct webpage* curr = pages[z];
        printf("%s %.4lf\n", curr->name, curr->rank);
    }

    return quit();

}

sample input:

8
4
a
b
c
d
4
a a

output:

error6

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初熏 2024-11-14 03:53:31
char n[20];
[ ... ]
    if (scanf(" %c", n) != 1 || has(n, i) != NULL) {

scanf%c 格式说明符仅读取一个字符。因此,n 由您键入的字符以及调用 scanf() 之前堆栈上发生的任何垃圾组成。如果您使用 %s,它将由您键入的字符加上一个用于终止字符串的 NUL 字节以及您不关心的垃圾组成。

另请注意,您可以使用宽度说明符来限制 scanf() 读取的字符数,如下所示:(

scanf("%19s", n)

意思是:读取 19 个字符并添加一个 NUL 字节)。否则,您的缓冲区可能会溢出,可能导致任意代码执行(或者至少在非恶意用户使用时崩溃)。

char n[20];
[ ... ]
    if (scanf(" %c", n) != 1 || has(n, i) != NULL) {

The %c format specifier for scanf reads only one character. So n consists of the character you typed plus whatever garbage happened to be on the stack before you called scanf(). If you use %s, it will consist of the character you typed plus a NUL byte for terminating the string plus garbage you don't care about.

Also note that you can limit the amount of characters scanf() reads by using a width specifier, as in:

scanf("%19s", n)

(meaning: read 19 characters and add a NUL byte). Otherwise, your buffer could overflow, possibly leading to arbitrary code execution (or at least a crash when used by non-malicious users).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文