Стек Разрушение / BackTrace

0

Я написал небольшой фрагмент кода, который должен взять массив символов и сделать его похожим на то, что компьютер печатает текст. Достаточно просто, не так ли? Но когда я его запустил, Терминал сказал мне следующее:

*** stack smashing detected ***: ./TYPE terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb759aeb5]
/lib/i386-linux-gnu/libc.so.6(+0x104e6a)[0xb759ae6a]
./TYPE[0x80486a9]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb74af4d3]
./TYPE[0x8048591]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 1580147    /home/jeremy/Desktop/programming/cpp/Jumping into C++/TYPE
08049000-0804a000 r--p 00000000 08:01 1580147    /home/jeremy/Desktop/programming/cpp/Jumping into C++/TYPE
0804a000-0804b000 rw-p 00001000 08:01 1580147    /home/jeremy/Desktop/programming/cpp/Jumping into C++/TYPE
08a30000-08a51000 rw-p 00000000 00:00 0          [heap]
b7449000-b744b000 rw-p 00000000 00:00 0 
b744b000-b7467000 r-xp 00000000 08:01 4195157    /lib/i386-linux-gnu/libgcc_s.so.1
b7467000-b7468000 r--p 0001b000 08:01 4195157    /lib/i386-linux-gnu/libgcc_s.so.1
b7468000-b7469000 rw-p 0001c000 08:01 4195157    /lib/i386-linux-gnu/libgcc_s.so.1
b7469000-b7493000 r-xp 00000000 08:01 4198259    /lib/i386-linux-gnu/libm-2.15.so
b7493000-b7494000 r--p 00029000 08:01 4198259    /lib/i386-linux-gnu/libm-2.15.so
b7494000-b7495000 rw-p 0002a000 08:01 4198259    /lib/i386-linux-gnu/libm-2.15.so
b7495000-b7496000 rw-p 00000000 00:00 0 
b7496000-b763a000 r-xp 00000000 08:01 4198264    /lib/i386-linux-gnu/libc-2.15.so
b763a000-b763c000 r--p 001a4000 08:01 4198264    /lib/i386-linux-gnu/libc-2.15.so
b763c000-b763d000 rw-p 001a6000 08:01 4198264    /lib/i386-linux-gnu/libc-2.15.so
b763d000-b7640000 rw-p 00000000 00:00 0 
b7640000-b7718000 r-xp 00000000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7718000-b7719000 ---p 000d8000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7719000-b771d000 r--p 000d8000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b771d000-b771e000 rw-p 000dc000 08:01 8786914    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b771e000-b7725000 rw-p 00000000 00:00 0 
b773e000-b7742000 rw-p 00000000 00:00 0 
b7742000-b7743000 r-xp 00000000 00:00 0          [vdso]
b7743000-b7763000 r-xp 00000000 08:01 4198254    /lib/i386-linux-gnu/ld-2.15.so
b7763000-b7764000 r--p 0001f000 08:01 4198254    /lib/i386-linux-gnu/ld-2.15.so
b7764000-b7765000 rw-p 00020000 08:01 4198254    /lib/i386-linux-gnu/ld-2.15.so
bffc0000-bffe1000 rw-p 00000000 00:00 0          [stack]
abcdefghijklmnopqrstuvwxyzAborted (core dumped)

Я новичок в C++ (у меня есть фон C), и я понятия не имею, что такое разбивка или обратная трассировка стека. если вы можете мне помочь, это очень поможет! Вот код:

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <unistd.h>

using namespace std;

void type(char letters[]);

int main(){

    char letters[27] = "abcdefghijklmnopqrstuvwxyz";
    system("clear");
    type(letters);

    return 0;
}

void type(char letters[]){

    unsigned int wait = 30000000;

    system("clear");
    for(int i = 0; letters[i] != '\n'; i++){
        usleep(wait)
        cout << letters[i];
    }

}
  • 0
    Вы ищете \ n, которого там нет; строки заканчиваются нулем.
  • 0
    ТАК, если я установлю буквы [27] = '\ n', это исправит это?
Показать ещё 5 комментариев
Теги:
stack-smash
backtrace

5 ответов

2

Предполагается, что строки в C++ заканчиваются на нуль, т.е. Их последний символ равен \0. В вашем коде цикл не заканчивается в конце строковых letters потому что вы ищете символ \n который на самом деле не существует в этой строке.

Первое исправление

Завершите строку символом, который вы ищете в своем цикле:

char letters[28] = "abcdefghijklmnopqrstuvwxyz\n";

Второе исправление

Завершите цикл, ища существующий символ конца строки \0:

for(int i = 0; letters[i] != '\0'; i++)

Третье исправление

Используйте правильную проверку длины строки в качестве критерия завершения цикла:

int len = strlen(letters);
for(int i = 0; i < len; i++)

Или любая комбинация этих трех.

В общем, никогда не рекомендуется объявлять строку как массив фиксированного размера, поэтому используйте const char *letters = "..."; вместо.

1

Вы находитесь в бесконечном цикле

Вы ищете '\n' которого не существует. Вы должны искать нулевой символ \0

for(int i = 0; letters[i] != '\0'; ++i){
    usleep(wait)
    cout << letters[i];
}
  • 0
    За исключением того, что теперь длина массива должна быть 28
  • 0
    ... и добавленный жесткий терминатор бесполезен. в конце этой строки уже есть один подарок. Совет по поиску нулевого символа, а не '\n' является правильным, учитывая исходную строку ввода.
Показать ещё 1 комментарий
0

Одно из двух решений, которое вы можете использовать здесь.

1) Вы можете включить \n в цикл, но это должно быть в самом массиве, и размер массива должен быть увеличен на 1 на буквы [28].

2) Вы сохраняете массив, как вы его объявили, но цикл for будет

for(int i = 0; letters[i]; i++){
   cout << letters[i];
}

Второе решение, вам не придется менять размер массива, и цикл будет продолжаться до конца массива

0

Вы должны использовать std::string если вы используете C++. Это будет отслеживать длину для вас, но вы также можете использовать итераторы.

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <unistd.h>

using namespace std;

void type(const string &);

int main(){

    string letters = "abcdefghijklmnopqrstuvwxyz";
    system("clear");
    type(letters);

    return 0;
}

void type(const string &letters)
{
    unsigned int wait = 30000000;

    system("clear");
    for(string::const_iterator it = letters.begin(); it != letters.end(); it++)
    {
        usleep(wait)
        cout << *it;
    }
}

Хотя, если хотите, вы все равно можете получить доступ к символам строки по индексу, например:

void type(const string &letters)
{
    unsigned int wait = 30000000;

    system("clear");
    for(size_t i = 0; i < letters.length(); i++)
    {
        usleep(wait)
        cout << letters[i];
    }
}
0

В дополнение к проблемам конца строки, отмеченным другими комментаторами, ваш код, вероятно, не даст вам эффекта, который вы хотите, потому что вы используете cout. Этот выходной поток буферизует все, пока вы все равно не отправляете новую строку, поэтому ваша "набрав" появится сразу, когда будет напечатана окончательная новая строка.

Вы можете получить эффект "один-на-один-на-время", напечатав cerr или сбросив cout после того, как каждый символ должен быть напечатан.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню