2009-06-04 87 views
1

我一直在开发一段时间的开源项目,http://gtkworkbook.sourceforge.net/,最近遇到了一个问题,就像我正在圈子里。我很确定有一个堆问题,但我一直在查看这个代码太长,以找出它到底是什么。Valgrind:Invaild阅读的大小8

所以,简而言之,我正在做的是在使用libcs​​v解析器的同时,将一个内存块从N个指针重新分配给M个指针。如果有其他列,我想将数组的最大大小增加到当前大小的2倍。下面是当前的代码:


struct csv_column { 
    Sheet * sheet; 
    Cell ** array; 
    int & array_max; 
    int & array_size; 
    int row; 
    int field; 
    char * value; 
    }; 

    static void 
    cb1 (void * s, size_t length, void * data) { 
    struct csv_column * column = (struct csv_column *) data; 
    int & array_max = column->array_max; 

    // Resize the cell array here. 
    if (column->field >= array_max) { 
     int max = (2 * array_max); 
     (column->array) = (Cell **) g_realloc ((column->array), max * sizeof (Cell*)); 

     for (int ii = array_max; ii array)[column->field] == NULL) 
     (column->array)[column->field] = cell_new(); 

    Cell * cell = (column->array)[column->field]; 
    cell->set_row (cell, column->row); 
    cell->set_column (cell, column->field++); 
    cell->set_value_length (cell, s, length); 
    } 

    CsvParser::CsvParser (Workbook * wb, 
      FILE * log, 
      int verbosity, 
      int maxOfFields) { 
    this->wb = wb; 
    this->log = log; 
    this->verbosity = verbosity; 
    this->sizeOfFields = 0; 
    this->maxOfFields = maxOfFields; 
    this->fields = (Cell **) g_malloc (maxOfFields * sizeof (Cell*)); 

    for (int ii = 0; ii maxOfFields; ii++) 
     this->fields[ii] = NULL; 
    } 

    CsvParser::~CsvParser (void) { 
    for (int ii = 0; ii maxOfFields; ii++) { 
     if (this->fields[ii]) 
     this->fields[ii]->destroy (this->fields[ii]); 
    } 

    g_free (this->fields); 
    } 

这里是Valgrind的输出:

 
==28476== Thread 9: 
==28476== Invalid read of size 8 
==28476== at 0x771AF4F: sheet_method_apply_cellarray (sheet.c:351) 
==28476== by 0xD930DB7: largefile::CsvParser::run(void*) (CsvParser.cpp:147) 
==28476== by 0xDD624C8: concurrent::thread_run(void*) (Thread.cpp:28) 
==28476== by 0xA7B73B9: start_thread (in /lib/libpthread-2.9.so) 
==28476== by 0x80DBFCC: clone (in /lib/libc-2.9.so) 
==28476== Address 0xbc5d4a8 is 0 bytes inside the accessing pointer's 
==28476== once-legitimate range, a block of size 160 free'd 
==28476== at 0x4C25D4F: free (vg_replace_malloc.c:323) 
==28476== by 0xD9314CA: largefile::cb1(void*, unsigned long, void*) (CsvParser.cpp:57) 
==28476== by 0xDB42681: csv_parse (in /home/jbellone/work/gtkworkbook/lib/libcsv.so) 
==28476== by 0xD930D00: largefile::CsvParser::run(void*) (CsvParser.cpp:136) 
==28476== by 0xDD624C8: concurrent::thread_run(void*) (Thread.cpp:28) 
==28476== by 0xA7B73B9: start_thread (in /lib/libpthread-2.9.so) 
==28476== by 0x80DBFCC: clone (in /lib/libc-2.9.so) 
==28476== 
==28476== Invalid read of size 8 
==28476== at 0x771AF66: sheet_method_apply_cellarray (sheet.c:351) 
==28476== by 0xD930DB7: largefile::CsvParser::run(void*) (CsvParser.cpp:147) 
==28476== by 0xDD624C8: concurrent::thread_run(void*) (Thread.cpp:28) 
==28476== by 0xA7B73B9: start_thread (in /lib/libpthread-2.9.so) 
==28476== by 0x80DBFCC: clone (in /lib/libc-2.9.so) 
==28476== Address 0xbc5d4a8 is 0 bytes inside the accessing pointer's 
==28476== once-legitimate range, a block of size 160 free'd 
==28476== at 0x4C25D4F: free (vg_replace_malloc.c:323) 
==28476== by 0xD9314CA: largefile::cb1(void*, unsigned long, void*) (CsvParser.cpp:57) 
==28476== by 0xDB42681: csv_parse (in /home/jbellone/work/gtkworkbook/lib/libcsv.so) 
==28476== by 0xD930D00: largefile::CsvParser::run(void*) (CsvParser.cpp:136) 
==28476== by 0xDD624C8: concurrent::thread_run(void*) (Thread.cpp:28) 
==28476== by 0xA7B73B9: start_thread (in /lib/libpthread-2.9.so) 
==28476== by 0x80DBFCC: clone (in /lib/libc-2.9.so) 

sheet.c线351


    gtk_sheet_set_cell_text (GTK_SHEET (sheet->gtk_sheet), 
       array[ii]->row, 
       array[ii]->column, 
       array[ii]->value->str); 

从sheet.c整体功能:


static void 
sheet_method_apply_cellarray (Sheet * sheet, 
        Cell ** array, 
        gint size) 
{ 
    ASSERT (sheet != NULL); 
    g_return_if_fail (array != NULL); 

    gdk_threads_enter(); 

    /* We'll see how this performs for now. In the future we may want to go 
    directly into the GtkSheet structures to get a little more performance 
    boost (mainly because we should not have to check all the bounds each 
    time we want to update). */ 
    for (gint ii = 0; ii gtk_sheet), 
       array[ii]->row, 
       array[ii]->column, 
       array[ii]->value->str); 

    if (!IS_NULLSTR (array[ii]->attributes.bgcolor->str)) 
     sheet->range_set_background (sheet, 
        &array[ii]->range, 
        array[ii]->attributes.bgcolor->str); 

    if (!IS_NULLSTR (array[ii]->attributes.fgcolor->str)) 
     sheet->range_set_foreground (sheet, 
        &array[ii]->range, 
        array[ii]->attributes.fgcolor->str); 

    /* Clear all of the strings */ 
    g_string_assign (array[ii]->value, ""); 
    g_string_assign (array[ii]->attributes.bgcolor, ""); 
    g_string_assign (array[ii]->attributes.fgcolor, ""); 
    } 

    gdk_threads_leave(); 
} 

CSV解析器线程


    void * 
    CsvParser::run (void * null) { 
    this->running = true; 
    std::queue queue; 
    struct csv_parser csv; 
    struct csv_column column = {this->wb->sheet_first, 
       this->fields, 
       this->maxOfFields, 
       this->sizeOfFields, 
       0, 
       0, 
       new char [1024]}; 

    if (csv_init (&csv, CSV_STRICT) != 0) { 
     std::cerr running == true) { 
     if (this->inputQueue.size() > 0) { 

    // Lock, copy, clear, unlock. - Free this up. 
    this->inputQueue.lock(); 
    this->inputQueue.copy (queue); 
    this->inputQueue.clear(); 
    this->inputQueue.unlock(); 

    while (queue.size() > 0) { 
     std::string buf = queue.front(); queue.pop(); 
     size_t bytes = buf.length(); 

     if (this->running == false) 
     break; 

     if ((bytes = csv_parse (&csv, buf.c_str(), bytes, cb1, cb2, &column)) == bytes) { 
     if (csv_error (&csv) == CSV_EPARSE) { 
      std::cerr wb->sheet_first->apply_array (this->wb->sheet_first, 
              this->fields, 
              this->sizeOfFields); 

     if (column.row >= (column.sheet)->max_rows) 
     column.row = 0; 
    } 
     } 
     concurrent::Thread::sleep(1); 
    } 

    return NULL; 
    } 
+0

你能缩小一点吗? sheet.c中的第351行是什么。这听起来像您正在读取您尚未分配或已被释放的内存中的数据。 – Kekoa 2009-06-04 21:07:29

+0

好的,对不起,其附加。 – 2009-06-04 21:22:40

回答

2

我的猜测是,你正在运行到与线程的竞争条件。 Cb1在解析器尝试使用它时重新分配数组。在realloc之后,旧地址不再有效,这就是您的无效读取来自哪里。您需要在阵列周围放置一个锁(可能是读写器锁)以防止发生此问题。如果可能的话,尝试单线程运行此代码以查看问题是否重现。如果不是,那么这是一个线程问题,否则它是完全不同的。