所以,我在相当长的一段时间内没有使用太多的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(¤t->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(¤t->lock)!=0) //if lock attempt fails
{
while(--i>=0)
{
pthread_mutex_unlock(¤t->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)的默认操作终止进程
答案 0 :(得分:1)
在main()中你写道:
char * in;
...
while(1)
{
printf("> ");
scanf("%s",&in);
我认为scanf()不会为你调用malloc()。