2014-02-13 2 views
2
int fromVectoEigen(vector<string> & source, double ** & array, int & n) 
{ 
    cout<<"n:"<<n<<'\n'; 
    int counter = 0; 

    for (int j = n-1 ; j >= 0 ; j--) // iterate through each line 
    { 
     string mystring = source.back(); // take last line 

     counter++; 
     char * str = new char [mystring.length()+1]; 
     std::strcpy (str, mystring.c_str()); // copy string to char array 
     char * pch; // pointer to tokens 
     pch = strtok (str," ,-"); 
     for(int i = 0 ; i<3 ; i++) // dismiss first 3 columns 
     { 

      pch = strtok (NULL, " ,-"); 
     } 

     for (int i= 0 ; i<n ; i++) 
     { 
      double val = atof(pch); // cast char to double 

      //array[j][i]= val; 
      //cout<<array[j][i]<<'\t'; 
      //pch = strtok (NULL, " ,-"); 
     } 
     // 
     //source.pop_back(); 

     } 

    return 0; 
} 

Привет!Память утечка strtok & atof

С помощью этой функции я хочу читать в матрице от файла до двухмерного массива. . Матрица имеет столько строк, сколько столбцов. И я хочу разделить строки по пространству с strtok. Линии были уже прочитаны в векторе в другой функции (которая работала - истекла). Поэтому я не знаю проблему, потому что я пытался запустить ее с небольшой матрицей 4 столбца 4 строки, которые отлично работали! Теперь я хотел попробовать его с большой матрицей, которая имеет более 1000 строк и столько столбцов. и я получаю сообщение об ошибке от Valgrind:

Invalid считывания размера 1 == 26501 == в 0x58A87AB: _ _strtod_l_internal (strtod_l.c: 538) == 26501 == по 0x4015BB: fromVectoEigen (std :: vector> &, double ** &, int &) (topo.cpp: 70) == 26501 == by 0x40362B: main (main.cpp: 36) == 26501 == Адрес 0x0 не является stack'd, malloc'd или (недавно) free'd

Я пробовал/раскомментировать метод и все работает отлично до того, где я использую atof .... который я не понимаю, потому что он отлично работал с малой матрицей

Значения в большой матрице выглядят так: 0.11991517 где, как и в малой тестовой матрице I имели только значения, равные 0 или 0.1

Надеюсь, я достаточно объяснил ... pls запросить дополнительную информацию, если необходимо.

+2

Эй, вы уверены, что у вас есть четвертая колонка? strtok может вернуть NULL, если вы прошли последний токен. (небезопасно доверять, что есть n токенов, вы можете дважды проверить и посмотреть, действительно ли этого достаточно) –

+0

Кроме того, во втором цикле for, если n корректно, и у вас одинаковое количество столбцов и строк, для должен идти до n-3 (потому что вы уже пропустили 3) –

+0

Да, дело в том, что все работает отлично для одного тестового файла, но просто не для другого. да, я знаю, что я уже пропустил три. это вариант, когда есть три столбца описания до начала запуска матрицы (но я прокомментировал это). – dieHellste

ответ

3

Вы назначаете str, но вы никогда не освобождаете его ... и с кодом, который у вас есть, вы никогда не сможете. Таким образом, каждый раз, когда вы вызываете эту функцию, вы будете утечки памяти.

Вы должны либо добавить delete [] str;, когда закончите, либо вообще не используете динамическую память, и придерживайтесь std::string.

Кроме того, вы можете избежать всей проблемы с конверсией и просто использовать std::istream::operator>> (например, используя std::istringstream) для анализа вашего ввода.

Что-то вроде этого (непроверенные) должны работать лучше для вас:

struct reader : std::ctype<char> 
{ 
    reader() : std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() 
    { 
     static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask()); 
     rc['\n'] = std::ctype_base::space; 
     rc[','] = std::ctype_base::space; 
     rc['-'] = std::ctype_base::space; 
     rc[' '] = std::ctype_base::space; 
     rc['\t'] = std::ctype_base::space; 
     return &rc[0]; 
    } 
}; 

int fromVectorEigen(const std::vector<std::string>& source, std::vector<std::vector<double>>& destination) 
{ 
    reader rdr; 
    std::for_each(source.rbegin(), source.rend(), [&](const std::string& s) 
    { 
     std::istringstream iss(s); 
     iss.imbue(std::locale(), &rdr); 
     std::string ignored_columns; 
     double value; 
     iss >> ignored_columns >> ignored_columns >> ignored_columns; 
     std::vector<double> values; 
     while (iss >> value) 
     { 
      values.push_back(value); 
     } 
     destination.push_front(values); 
    }); 
    return 0; 
} 
+0

И вместо использования необработанных указателей и 'delete', назначая выделенную память' unique_ptr'/'auto_ptr' или' shared_ptr'. – Peter

+0

Это будет 'delete [] str' no? – Sinkingpoint

+0

@Quirliom Да, это будет 'delete []'. Однако лучшим решением является не использование (ручная) динамическая память. –

0

Если вы хотите остаться с этой текущей конструкции не используются потоки, но устранить явное выделение памяти, вы можете использовать зЬй :: вектор:

#include <vector> 
    //... 
    std::vector<char> str(mystring.begin(), mystring,end()); 
    str.push_back(0); 
    char * pch; // pointer to tokens 
    pch = strtok (&str[0]," ,-"); 
+0

это вызывает ту же ошибку, что и раньше – dieHellste

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