C

时间:2015-10-22 17:45:16

标签: c multithreading

所以,我在相当长的一段时间内没有使用太多的C,而且对malloc来说从未如此舒服。我不知道这是否是问题的根源,但是我遇到了分段错误,如果有人在这里看到任何可能出现问题的明显错误,那么找到它会省去很多麻烦,因为我我甚至不确定从哪里开始。

提供给主要关于启动的信息:线程限制,帐户限制,输出文件。 可能的输入

  

TRANS [acct id 1] [amount] [acct id 2] [amount]等...

     

检查[acct id]

     

END

输出不多,大部分信息都提供给输出文件。

如果此代码特别难以理解或遵循,请告诉我,我会尝试解释。

编辑:来自valgrind的所有内存错误都是由对strtok()的调用引起的。我搞砸了这个,但似乎无法修复它。如何在不导致这些错误的情况下使用扫描变量中的strtok()?

appserver.c

- 主程序

#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<string.h>
#include "Bank.c"
#include "appserver.h"




struct account *accounts=NULL;
pthread_t *threads=NULL;
char *threadstatus=NULL;
int done=0;
char busywait=0;
FILE * f;

int main(int argc, char **argv){
    int threadcount, banksize;
    char* outputpath;
    if(argc<4)
    {
        threadcount=1;
        banksize=100;
        outputpath="output.txt";
    }
    else
    {
        char *tstr=argv[1];
        char *sstr=argv[2];
        outputpath=argv[3];
        threadcount=(int) strtol(tstr, NULL, 10);
        banksize=(int) strtol(sstr, NULL, 10);
    }




    int reqID=0;
    struct request *req1, *req2;
    req1 = (struct request *) malloc( sizeof(struct request) );
    char * in;
    char *s;

    initialize_status(threadcount);
    threads = (pthread_t *) calloc( threadcount, sizeof(pthread_t) );
    initialize_accounts(banksize);
    initialize_mutex(banksize);
    f=fopen(outputpath,"w");
    int stringsize=1000;

    int threadindex=0;
    int i;
    while(1)
    {

        printf("> ");
        getline(&in, &stringsize, stdin);
        s=strtok(in," ");
        if( strcmp( (const char *) s, "CHECK") == 0 )
        {
            req2 = (struct request *) malloc( sizeof(struct request) );
            reqID++;
            req1->type = 'b';
            s=strtok(NULL," ");
            req1->balanceID = (int) strtol( s, NULL, 10);
            req1->next = req2;
            req1->requestID = reqID;
            threadindex=nextthread(threadcount);
            if(threadindex<0)
            {
                busywait=1;
                while(busywait==1)
                {
                    //do nothing, waiting for a thread to finish
                }
                threadindex=nextthread(threadcount);
            }
            req1->thread=threadindex;
            pthread_create(&threads[threadindex], NULL, (void *)&workthread, &req1);
            req1=req2;
        }
        else if( strcmp( (const char *) s, "TRANS") == 0 )
        {
            req2 = (struct request *) malloc( sizeof(struct request) );
            i=0;
            reqID++;
            req1->type = 't';
            while(s!=NULL&&i<10)
            {
                s = strtok(NULL," ");
                req1->transIDs[i] = (int) strtol( s, NULL, 10);
                if((s = strtok(NULL," "))==NULL)
                {
                     printf("Bad input: \n");
                     break;
                }
                req1->transvals[i] = (int) strtol( s, NULL, 10);
                i++;
            }
            req1->next = req2;
            req1->requestID = reqID;
            threadindex=nextthread(threadcount);
            if(threadindex<0)
            {
                busywait=1;
                while(busywait==1)
                {
                    //do nothing
                }
                threadindex=nextthread(threadcount);
            }
            req1->thread=threadindex;
            pthread_create(&threads[threadindex], NULL, (void *)&workthread, &req1);
            req1=req2;
        }
        else if( strcmp( (const char *) s, "END") == 0)
        {
            req1->type = 'e';
            threadindex=nextthread(threadcount);
            if(threadindex<0)
            {
                busywait=1;
                while(busywait==1)
                {
                    //do nothing
                }
                threadindex=nextthread(threadcount);
            }
            req1->thread=threadindex;
            pthread_create(&threads[threadindex], NULL, (void *)&workthread, &req1);
            for( i = 0; i < threadcount; i++)
                pthread_join( threads[i], NULL);
            free(accounts);
            free(threads);
            break;
        }
        else
        {
            printf("Try again\n");
        }
        free(in);
    }
    return 0;
}

void *workthread(struct request *data)
{
    threadstatus[data->thread]='b';
    int value;
    int i, balance;
    printf("< ID %d\n",data->requestID);
    while(1)
    {
        if(data->type == 't')
        {   
            int transamt[10]={0,0,0,0,0,0,0,0,0,0};
            int values[10]={0,0,0,0,0,0,0,0,0,0};
            for(i=0;i<10;i++)
            {
                if(!data->transIDs[i])
                    break;
                transamt[i]=data->transvals[i];
                value=read_account(data->transIDs[i]);
                if((values[i]=value+transamt[i])<0)
                {
                    busywait = 0;
                    threadstatus[data->thread]='a';
                    fprintf(f,"%d ISF %d\n",data->requestID,data->transIDs[i]);
                    return;
                }
            }
            if(translock(data->transIDs) == 1)
            {
                int ID;
                for(i=0;i<10;i++)
                {
                    ID=data->transIDs[i];
                    accounts[ID-1].value=values[i];
                    write_account(data->transIDs[i],values[i]);
                }
            }
            transunlock(data->transIDs);
            busywait=0;
            threadstatus[data->thread]='a';
            fprintf(f,"%d OK\n",data->requestID);
            return;
        }
        else if(data->type == 'b')
        {
            int balance=read_account(data->balanceID);
            fprintf(f,"%d BAL %d\n",data->requestID,balance);
            threadstatus[data->thread]='a';
            busywait=0;
            return;
        }


        else if(data->type == 'e')
        {
            done=1;
            return;
        }
    }
}

int transunlock(int ids[])
{
    struct account *current;
    int i=0;
    for(i=9;i>=0;i--)
    {
        current=&accounts[ids[i]-1];
        if(ids[i]<1)
            continue;
        pthread_mutex_unlock(&current->lock); //unlock previous account
    }
    return;
}

int translock(int ids[])
{
    struct account *current;
    int i=0;
    for(i=0;i<10;i++)
    {
        current=&accounts[ids[i]-1];
        if(ids[i]<1||pthread_mutex_trylock(&current->lock)!=0) //if lock attempt fails
        {
            while(--i>=0)
            {
                pthread_mutex_unlock(&current->lock); //unlock previous account
            }
            return 0;
        }
        current++;
    }
    return 1;
}

int initialize_mutex(int n)
{
    accounts=(struct account *) malloc(sizeof(struct account) * n);
    if(accounts==NULL)
        return 0;
    int i;
    for(i=0;i<n;i++)
    {
        accounts[i].value=0;
    }
    return 1;
}

int initialize_status(int n)
{
    threadstatus = (char *) malloc( sizeof(char) * n );
    int k;
    for(k=0;k<n;k++)
    {
        threadstatus[k]='a';
    }
}

int nextthread(int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        if(threadstatus[i]=='a')
            return i;
    }
    return -1;
}

appserver.h

#include<pthread.h>

struct account{
    pthread_mutex_t lock;
    int value;
};

struct request{
    char type; //'b' for balance check, 't' for transaction, 'e' for exit
    int transIDs[10];
    int transvals[10];
    int balanceID;
    struct request *next;
    int requestID;
    int thread;
};


void *workthread(struct request *data);
int transunlock(int ids[]);
int translock(int ids[]);
int initialize_mutex(int n);
int initialize_status(int n);
int nextthread(int n);

Bank.c

/**  Do not modify this file  **/

#include "Bank.h"
#include <stdlib.h>


int *BANK_accounts; //Array for storing account values

/*
 *  Intialize back accounts
 *  Input:  int n - Number of bank accounts
 *  Return:  1 if succeeded, 0 if error
 */
int initialize_accounts( int n )
{
    BANK_accounts = (int *) malloc(sizeof(int) * n);
    if(BANK_accounts == NULL) return 0;

    int i;
    for( i = 0; i < n; i++)
    {
        BANK_accounts[i] = 0;
    }
    return 1;
}

/*
 *  Read a bank account
 *  Input:  int ID - Id of bank account to read
 *  Return:  Value of bank account ID
 */
int read_account( int ID )
{
    usleep( 100000 );
    return BANK_accounts[ID - 1];
}

/*
 *  Write value to bank account
 *  Input:  int ID - Id of bank account to write to
 *  Input:  int value - value to write to account
 */
void write_account( int ID, int value)
{
    usleep( 100000 );
    BANK_accounts[ID - 1] = value;
}

Bank.h

/**  Do not modify this file  **/

/*
 *  These functions do not provide any error checking.
 *  If an invalid input is supplied the behavior is
 *  undefined.
 */

/*
 *  Intialize n bank accounts with IDs from 1 to n and values of 0.
 *  Input:  int n - Number of bank accounts, must be larger than 0
 *  Return:  1 if succeeded, 0 if error
 */
int initialize_accounts( int n );

/*
 *  Read a bank account
 *  Input:  int ID - Id of bank account to read
 *  Return:  Value of bank account ID
 */
int read_account( int ID );

/*
 *  Write value to bank account
 *  Input:  int ID - Id of bank account to write to
 *  Input:  int value - value to write to account
 */
void write_account( int ID, int value);

就像我之前说的那样,valgrind上的所有错误都与strtok()调用有关,如下所示:

条件跳转或移动取决于未初始化的值

使用大小为8的未初始化值

读取大小为1

使用信号11(SIGSEGV)的默认操作终止进程

1 个答案:

答案 0 :(得分:1)

在main()中你写道:

char * in;
...
while(1)
{
    printf("> ");
    scanf("%s",&in);

我认为scanf()不会为你调用malloc()。