【问题标题】:String logic error in C++C++中的字符串逻辑错误
【发布时间】:2014-12-05 08:37:51
【问题描述】:

我正在编写一个程序,该程序将使用位操作评估竞争条件,然后还将使用信号量锁定/解锁来消除这些竞争条件。

我使用“./raceTest 5 6 3 6 unlock”很好地运行程序。所有的输出过去都很好。但现在它会因解锁 arg 而崩溃。

当我尝试使用这些 args 编译它时,我的程序崩溃了:./raceTest 5 6 3 6 lock(或任何带有“lock”的 args)

这就是“锁定”命令的输出。它现在以这种方式崩溃......即使它没有因为“解锁”而崩溃并且正确显示所有内容。

./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;
}

编辑:: 这是我做bt的时候得到的,恐怕我不是很明白这东西是什么意思……

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

第二次编辑:无论我只是为冲突处理线程还是使用信号量。我所做的唯一更改是将数组参数从 nBuffers 更改为 nWorkers,然后测试 rand 的输出以查看它是否产生未定义的行为。

[ariley@bert 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

【问题讨论】:

  • 当它在调试器中崩溃时输入bt 来查看堆栈。这有望帮助您缩小范围。
  • 如果您查看函数调用堆栈(通过使用bt 命令),您将看到代码中发生异常的位置。将up 调用堆栈转到您的代码并检查变量的值。至少,编辑您的问题以包含函数调用堆栈,并指出问题在 您的 代码中的位置。
  • 它在这一行崩溃:nBuffers = atoi(argv[1]);
  • 该函数调用,以及调试器中的错误(似乎是从std::string 类抛出的异常),程序的输出,这些都不是事物相互匹配。
  • 关于你在调试器中遇到的崩溃,这是因为你运行你的程序没有参数。看到main 函数的参数了吗?它说argc=1。在调试器中,您使用run 命令运行程序,但run 命令的参数是您程序的参数,因此您应该像run 5 6 3 6 lock 一样运行它

标签: c++ string multithreading gdb


【解决方案1】:
pthread_t tid[nBuffers];

应该是

pthread_t tid[mWorkers];

除非参数集是 'nolock'(不是 'unlock'),否则不要初始化 tid[] 数组,因此使用无效参数调用 pthread_join(tid[i], NULL)。

标记。

【讨论】:

  • 这是一个很好的观点。我绝对忽略了一些东西。我查了 pthread_create 但我不明白 tid 的值是如何定义的。我正在运行的输出有 2 个连续的 tid 值 6300416,然后一个非常大的 47840834492736。然后发生段错误。
  • 是的,因为正如我所说:“除非参数集是 'nolock'(不是 'unlock'),否则您不会初始化 tid[] 数组”。使用“5 6 3 6 nolock”运行,它会运行... if ( strcmp (s.c_str(), "nolock") == 0)
  • 实际上,这正是我说它之前运行时的意思。这就是我的输入。但它开始出现 lock 或 nolock 的段错误。
【解决方案2】:

谁能告诉我这是什么意思?

这意味着你做了(相当于)这个:

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

【讨论】:

  • 调用 pthread_create () 来创建工作线程的唯一路径(因此在调用 pthread_join () 时在 tid [] 中有一个有效条目)是当您使用 'nolock' 调用时。 .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多