2014-12-05 2 views
1

Я пишу программу, которая будет оценивать условия гонки, используя бит-манипуляции, а затем также устранит эти условия гонки, используя блокировку/разблокировку семафора.Ошибка строковой логики в C++

Я запускаю программу с помощью «./raceTest 5 6 3 6 unlock». Весь вывод, используемый для выдачи, прекрасен. Но теперь он падает с разблокировкой arg.

Моя программа падает, когда я пытаюсь скомпилировать его с этими аргументами, а также: ./raceTest 5 6 3 6 замка (или любые арг с «замком» по этому вопросу)

Это, насколько выхода идет с командой «lock». Это происходит так же, как и сейчас ... даже если это не сбой для «разблокировки» и отображает все правильно.

./raceTest 5 6 3 6 lock 
lock 
nBuffers is 5 
mWorkers is 6 
sleepMin is 3 
sleepMax is 6 
randarray 4 
randarray 3 
randarray 6 
randarray 3 
randarray 4 
randarray 4 
Segmentation fault 

Я пытался использовать GDB, и когда я запустил программу, я получаю эту ошибку с помощью GDB

Starting program: /mnt_nfs/home3/ugrad3/ariley/Desktop/cs361/hw5/raceTest 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000 
[Thread debugging using libthread_db enabled] 
terminate called after throwing an instance of 'std::logic_error' 
what(): basic_string::_S_construct NULL not valid 

Program received signal SIGABRT, Aborted. 
0x0000003156430265 in raise() from /lib64/libc.so.6 

Может кто-то пожалуйста, скажите мне, что это значит? Он работал раньше. Но теперь он не работает, и я не делал ничего, чтобы это ...

// raceTest program 
#include <string> 
#include <iostream> 
#include <stdlib.h> 
#include <time.h> 
#include <pthread.h> 
#include <sys/sem.h> 
#include <sys/types.h> 
#include <sys/stat.h> 

#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) 
/* union semun is defined by including <sys/sem.h> */ 
#else 
/* according to X/OPEN we have to define it ourselves */ 
union semun 
{ 
int val;    // value for SETVAL 
struct semid_ds *buf; // buffer for IPC_STAT, IPC_SET 
unsigned short *array; // array for GETALL, SETALL 
struct seminfo *_buf; // buffer for IPC_INFO 
}; 
#endif 

static int sem_id = 0; 
static int sem_semvalue(); 
static void del_semvalue(); 
static int semaphore_p(); 
static int semaphore_v(); 

using namespace std; 

// struct for the threads 
typedef struct thread 
{ 
int nbuffers; 
int ID; 
double sleepTime; 
int semID; 
int mutexID; 
int *buffer; 
int nReadErrors; 
} Thread_data; 

void *worker(void *targ) 
{ 
cout << "In worker function" << endl; 
// cast back to a struct variable to use 
Thread_data *data = (Thread_data*) targ; 

int errors=0; 

for (int i=0 ; i < data->nbuffers; i++) 
{ 
    // READ the value of buffers at that thread's ID, starting from current ID 
    int read = data->buffer[data->ID]; 
    usleep(data->sleepTime); 
    // see if the value changed after sleeping 
    int secondRead = data->buffer[data->ID]; 
    if (secondRead != read) 
    {   
     cout << " Worker " << data->buffer[data->ID] << " reported change from " << read << " to  secondRead " << secondRead; 
     cout << " in buffer " << i << endl; 
     errors ++; 
    } 

    read = (read + data->ID) % (data->nbuffers); // next read 

    usleep(data->sleepTime); 
    secondRead = data->buffer[read]; 
    if (secondRead != read) 
    {   
     cout << " Worker " << data->buffer[data->ID] << "reported change from " << read << " to secondRead " << secondRead; 
     cout << " in buffer " << i << endl; 
     errors ++; 
    } 

    // write operations to do 
    read = (read + data->ID) % (data->nbuffers); 
    usleep(data->sleepTime); 
    // add to the buffer array, or the WRITE 
    data->buffer[read] = secondRead + (1 << (data->ID - 1)); 
} 
data->nReadErrors = errors; // update 4. 
pthread_exit(NULL); 
} 


int main (int argc, char * argv[]) 
{ 
int i; // handle all command line arguements 
int nBuffers = 0; 
int mWorkers = 0; 
int sleepMin = 0; 
int sleepMax = 0; 
srand(time(NULL)); 
key_t key = IPC_PRIVATE; 
int rErrors = 0; 
int wErrors = 0; 

// parse command line arguments 
// USAGE: raceTest nBuffers nWorkers sleepMin sleepMax [ randSeed ] [ -lock | -nolock ] 
for (i=1 ; i<argc-1 ; i++) 
{ 
    // Check input 
    string s = argv[i]; 
    int num = atoi(s.c_str()); // UPDATE 5 
    //cout << "argv at " << i << " is " << num << endl; 

    if (num == 0) 
    { 
     cout << "USAGE: raceTest nBuffers nWorkers sleepMin sleepMax [ randSeed ] [ -lock | - nolock ]" << endl; 
     cout << "Exiting..." << endl; 
     exit(-1); 
    } 
} 
string s = argv[i++]; 
cout << s << endl; 

// set variables to command line arguments 
// nBuffers has restrictions 
nBuffers = atoi(argv[1]); 
if (nBuffers <= 2 || nBuffers >= 32) 
{ 
    cout << "nBuffers is the wrong size. Exiting" << endl; 
    exit (-1); 

    if (nBuffers != 3 || nBuffers != 7 || nBuffers != 11 || nBuffers != 17 || nBuffers !=5 
     || nBuffers != 13 || nBuffers != 19 || nBuffers != 23 || nBuffers != 31 || nBuffers != 29) 
    { 
      cout << "nBuffers must be prime. Exiting" << endl; 
      exit (-2); 
    } 
} 

mWorkers = atoi(argv[2]); cout << "nBuffers is " << nBuffers << endl; 
sleepMin = atoi(argv[3]); cout << "mWorkers is " << mWorkers << endl; 
sleepMax = atoi(argv[4]); cout << "sleepMin is " << sleepMin << endl; 
cout << "sleepMax is " << sleepMax << endl; 

int buffers[nBuffers]; 
double randWorkers[mWorkers]; 

// initialize the arrays 
for (int i=0 ; i<nBuffers ; i++) 
    buffers[i] = 0; 

for (int i=0 ; i<mWorkers ; i++) 
{ 
    // generate random number between sleepMin and sleepMax 
    int temp = rand() % (sleepMax - sleepMin + 1) + sleepMin; 
    randWorkers[i] = temp; 
    cout << "randarray " << randWorkers[i] << endl; 
} 

// sort the numbers in decreasing order 
for (int i=0 ; i<mWorkers ; i++) 
{ 
    for (int j=0 ; j< mWorkers ; j++) 
    { 
     if (randWorkers[i] < randWorkers[j]) 
     { 
      cout << "here" << endl; 
      // simple sorting 
      double temp = randWorkers[i]; 
      randWorkers[i] = randWorkers[j]; 
      randWorkers[j] = temp; 
      cout << randWorkers[i] << " "; 
     } 
    } 
} 
// other sorting method 
//sort (randWorkers, sizeof(randWorkers), greater<double>); 

// create an array of M structs and populate each with values needed 
// for the threads 
Thread_data threadVals[mWorkers]; 

for (int i=0 ; i<mWorkers ; i++) 
{ 
    threadVals[i].nbuffers = nBuffers; 
    threadVals[i].ID = i+1; 
    threadVals[i].sleepTime = randWorkers[i]; 
    threadVals[i].semID = -1; 
    threadVals[i].mutexID = -1; 
    threadVals[i].nReadErrors = 0; 
    threadVals[i].buffer = buffers; 
} 

// create an array of M (threads) where each runs the 
// worker() function 
pthread_t tid[nBuffers]; 

for (int i=0 ; i<mWorkers ; i++) 
{ 
    // don't do any locking 
    if (strcmp (s.c_str(), "nolock") == 0) 
    { 
     // pass a pointer to one of the structs 
     int value = pthread_create (&tid[i], NULL, worker, &threadVals[i]); 
     if (value != 0) 
     { 
      perror ("thread creation failed"); 
      exit(-3); 
     } 
     else 
      cout << "successful creation for " << tid[nBuffers] << endl; 
    } 

    // use semaphores for the locking 
    else if (strcmp(s.c_str() , "lock") == 0) 
    { 
     /*cout << "B-----" << endl; 
     int sem_id = semget(key, 1, IPC_CREAT|0666); 
     if (sem_id < 0) 
     { 
      perror ("Cannot create sem_id"); 
      exit(-5); 
     } 
     cout << "A-----" << endl; */ 
     ; 
    } 
} 

// wait for all of the threads to finish 
for (int j=0 ; j<mWorkers ; j++) 
{ 
    pthread_join(tid[j], NULL); 
} 

for (int i=0 ; i< nBuffers ; i++) 
{ 
    int size = 2^ mWorkers - 1; 
    if (buffers[i] == size) 
     break; // this particular index is the same 

    cout << "Bad bits for buffer[" << i <<"] = " ; 
    int diff = size^buffers[i]; 
    for (int j=0 ; j <mWorkers ; j++) 
    { 
     // perform a binary OR and then binary AND 
     int position = (diff) & (1<<j); 
     //cout << buffer[position] << W" "; 
     if (position) 
      cout << j << " " ; 
     wErrors++; 
    } 
    cout << endl; 
} 

// figure the total number of read errors 
for (int i=0 ; i<mWorkers ; i++) 
    rErrors = rErrors + threadVals[i].nReadErrors; 

cout << "Total Errors: " << "read errors: " << rErrors << " write errors " << wErrors << endl; 
return 0; 
} 

EDIT :: Это то, что я получил, когда я сделал БТ, я боюсь, что я действительно не понимаю, что значит этот материал. ..

Program received signal SIGSEGV, Segmentation fault. 
0x000000315643471a in ____strtoll_l_internal() from /lib64/libc.so.6 
(gdb) bt 
#0 0x000000315643471a in ____strtoll_l_internal() from /lib64/libc.so.6 
#1 0x0000003156431bd2 in atoi() from /lib64/libc.so.6 
#2 0x00000000004010a5 in main (argc=1, argv=0x7fffffffded8) at raceTest.cpp:171 
(gdb) up 
#1 0x0000003156431bd2 in atoi() from /lib64/libc.so.6 
(gdb) 
#2 0x00000000004010a5 in main (argc=1, argv=0x7fffffffded8) at raceTest.cpp:171 
171    nBuffers = atoi(argv[1]); 
(gdb) 
Initial frame selected; you cannot go up. 
(gdb) print nBuffers 
$1 = 0 

ВТОРОЙ EDIT: Независимо от того, если я просто отсеивание для столкновений или с помощью семафоров. Единственное изменение, которое я сделал, это изменение параметра массива от nBuffers до nWorkers, а затем тестирование выходного файла rand, чтобы определить, создает ли оно неопределенное поведение.

[[email protected] hw5]$ ./raceTest 5 6 3 6 lock 
5 
6 
3 
6 
5beforenBuffers is 5 
mWorkers is 6 
sleepMin is 3 
sleepMax is 6 
value of temp4 
randarray 4 
value of temp6 
randarray 6 
value of temp3 
randarray 3 
value of temp5 
randarray 5 
value of temp4 
randarray 4 
value of temp6 
randarray 6 
successful creation for 6300416 
In worker function 
successful creation for 6300416 
successful creation for 47840834492736 
Segmentation fault 
+1

Когда он выходит из строя в типе отладчика 'bt', чтобы увидеть стек. Это, надеюсь, поможет вам сузить его. –

+0

Если вы посмотрите на стек вызовов функций (с помощью команды 'bt'), вы увидите, где в вашем коде происходит исключение. Пройдите вверх по стеку вызовов к вашему коду и просмотрите значения переменных. По крайней мере, отредактируйте свой вопрос, чтобы включить стек вызовов функций, и укажите, где находится * ваш * код. –

+0

Он падает на этой строке: nBuffers = atoi (argv [1]); –

ответ

2
pthread_t tid[nBuffers]; 

должен быть

pthread_t tid[mWorkers]; 

Вы не инициализирует TID [] массив, если набор параметров не является 'NOLOCK' (не 'разблокировать'), и, следовательно, pthread_join (TID [ i], NULL) вызывается с недопустимым параметром.

Mark.

+0

Это хороший момент. Что-то я определенно забыл. Я посмотрел pthread_create, но я не понимаю, как определяются значения tid. Мой вывод, который я запускаю, имеет 2 последовательных значения 6300416 для tid, а затем один действительно большой на 47840834492736. Затем возникает ошибка seg. –

+0

Да, потому что, как я уже сказал, «вы не инициализируете массив tid [], если параметр не« nolock »(не« unlock »)». Запустите с «5 6 3 6 nolock», и он запустится ... if (strcmp (s.c_str(), «nolock») == 0) –

+0

Собственно, это именно то, что я имел в виду, когда я сказал, что он работает ранее. Это то, что у меня было для ввода. Но он начал сегрегацию для блокировки или нолока. –

0

Может кто-нибудь, пожалуйста, скажите мне, что это значит?

Это означает, что вы сделали (эквивалент) это:

char *cp = NULL; 
std::string s(cp); // throws logic_error 
+0

Единственный путь, который вызывает pthread_create() для создания рабочих потоков (и поэтому имеет допустимую запись в tid [] в вызове pthread_join()), когда вы вызываете «nolock» ... –

Смежные вопросы