2010-01-07 2 views
0

У меня есть система плагинов в моем проекте (работает на Linux), и часть этого является то, что модули имеют метод «запустить», такие как:Отладка коррупции параметра в C++?

void run(int argc, char* argv[]); 

Я звоню плагин и перейти к проверьте мой массив argv (после выполнения кучу других вещей) и массив поврежден. Я могу напечатать значения в верхней части функции, и они верны, но не позже в исполнении. Ясно, что что-то развращает кучу, но Я в недоумении, как я могу попытаться точно определить, что переписывает эту память. Valgrind не очень помог мне.

Пример кода по запросу:

Мой плагин выглядит так:

void test_fileio::run(int argc, char* argv[]) { 
    bool all_passed = true; 

    // Prints out correctly. 
    for (int ii=0; ii < argc; ii++) { 
    printf("Arg[%i]: %s\n", ii, argv[ii]); 
    } 

    <bunch of tests snipped for brevity> 

    // Prints out inccorrectly. 
    for (int ii=0; ii < argc; ii++) { 
    printf("Arg[%i]: %s\n", ii, argv[ii]); 
    } 
} 

Это связано в систему, которая выставляет его на питона, так что я могу назвать эти плагины как функции питона. Итак, я беру параметр строки в моей функции питона и разорвать, что из таким образом:

char** translate_arguments(string args, int& argc) { 
    int counter = 0; 
    vector<char*> str_vec; 

    // Copy argument string to get rid of const modifier 
    char arg_str[MAX_ARG_LEN]; 
    strcpy(arg_str, args.c_str()); 

    // Tokenize the string, splitting on spaces 
    char* token = strtok(arg_str, " "); 
    while (token) { 
    counter++; 
    str_vec.push_back(token); 
    token = strtok(NULL, " "); 
    } 

    // Allocate array 
    char** to_return = new char*[counter]; 
    for (int ii=0; ii < counter; ii++) 
    to_return[ii] = str_vec[ii]; 

    // Save arg count and return 
    argc = counter; 
    return to_return; 
} 

Полученный ARGC и ARGV затем передается в плагин, упомянутых выше.

+0

Вы можете включать образец кода, чтобы сделать его проще для нас коллег-SO пользователей, чтобы понять, что вы делаете? – t0mm13b

+0

Пример кода добавлен, он скелетный, потому что этот плагин довольно большой, но это дает вам суть проблемы. –

+0

Я думаю, что мы можем сказать, какова природа проблемы, но вы оставили все, что могло бы помочь в отношении фактического источника проблемы. Есть миллион различных вещей, которые могут повредить этот массив, но вы оставили весь этот код. – SoapBox

ответ

2

Как вызывается translate_arguments? Это отсутствует ...

Подготавливает ли массив указателей к символам перед вызовом функции run в плагине, так как функция run имеет параметр char *argv[]?

Это выглядит как линия, которая вызывает проблемы ... Судя по коду

 
// Allocate array 
char** to_return = new char*[counter]; 

Вы намерены выделить указатель на указатель на голец, двойной указатель, но он выглядит старшинство код немного запутан? Вы пробовали это так:

 
char** to_return = new (char *)[counter]; 

Кроме того, в вашем цикл, как показано ... вы не выделение пространства для самой строки, содержащейся в векторе ...?

 
for (int ii=0; ii < counter; ii++) 
    to_return[ii] = str_vec[ii]; 

// Should it be this way...??? 

for (int ii=0; ii < counter; ii++) 
    to_return[ii] = strdup(str_vec[ii]); 

На риске получения downvoted как OP не показывает, как translate_arguments называется и отсутствие дополнительной информации .... и недооценив если мой ответ неверен ...

Надеется, что это помогает, С уважением, Том.

+0

Я согласен с вашей второй частью (выделение памяти для строк). Как написано в настоящее время, указатели в векторе указывают на данные, которые хранятся в стеке, которые затем выходят за рамки (arg_str). После вызова translate_arguments существует, вероятно, некоторый код, который заканчивает переписывание этого пространства в стеке (локальные переменные и т. Д.). – Luke

+0

Уверен, что, похоже, решил проблему, спасибо! –

2

Посмотрите, как использовать контрольные точки доступа к памяти с помощью отладчика. Если у вас есть надежное репо, это будет определять вашу проблему за считанные секунды. В WinDbg, это:

ba w4 0x<address> 

Где ба означает «перерыв на доступ», «w4» является «написать 4 байта» (использование W8 на 64 битной системе) и «адрес», очевидно, адрес, который вы» видя поврежденный. gdb и Visual Studio имеют схожие возможности.

+0

Любая идея, как вы могли это сделать с помощью gdb? Похоже, именно то, что мне нужно. –

+0

Похоже http://stackoverflow.com/questions/58851/can-i-set-a-breakpoint-on-memory-access-in-gdb –

+0

Отлично, спасибо! –

0

если Valgrind и проверки кода не помогают, вы можете попробовать электрический забор

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