Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
1

Ошибка при чтении символов строки при создании объекта класса

26.03.2021, 17:42. Показов 3240. Ответов 9

Author24 — интернет-сервис помощи студентам
У меня имеется класс Song, в котором присутствуют поля имени песни (Name) и длительности песни (Duration). Также в этом классе есть конструктор, заполняющий поля стандартными значениями. При создании такого объекта в main() смотрю через отладчик, что в поле Name (а именно - Name -> _MyPair -> Базовое представление -> _MyVal2 -> _Bx -> _Ptr) есть надпись - "ошибка при чтении символов строки". Причем странно, что все время все компилилось и работало, но сегодня почему-то вылезло такое. Короче, сам код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Song
{
private:
    std::string Name;
    int Duration;
 
public:
    Song()
    {
        this->Name = "";
        this->Duration = 0;
    }
}
 
int main()
{
Song* song = new Song;
 
/* ... */
}
Пробовал уже и само поле инициализировать, и способ задания имени в конструкторе менять на такой, все без толку:
C++
1
this->Name = {}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.03.2021, 17:42
Ответы с готовыми решениями:

Ошибка при чтении объекта класса из файла
Долго я пытался решить проблему самостоятельно, а так же и искал ответы на форумах. Но в итоге не...

Ошибка при создании объекта класса
Приветствую, форумчане! Возник вопрос при создании объекта класса String. Что самое интересное,...

Ошибка при создании объекта класса
Здравствуйте. В коде ниже при попытке вывести код на экран возникает следующая ошибка: prog.cpp:...

Ошибка при создании объекта класса
Привет! Чтобы на протяжении всего поста было понятно о чём я говорю,в конце поста прикреплю код....

9
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
27.03.2021, 05:49  [ТС] 2
Примечательно еще то, что у меня есть другие классы тоже с полем string Name и с аналогичными конструкторами, но там все с этими именами в порядке. Глюк какой, что ли...
0
Вездепух
Эксперт CЭксперт С++
12641 / 6548 / 1758
Регистрация: 18.10.2014
Сообщений: 16,515
27.03.2021, 06:09 3
Цитата Сообщение от Skel Посмотреть сообщение
смотрю через отладчик, что в поле Name (а именно - Name -> _MyPair -> Базовое представление -> _MyVal2 -> _Bx -> _Ptr) есть надпись - "ошибка при чтении символов строки". Причем странно, что все время все компилилось и работало, но сегодня почему-то вылезло такое
Не понял. Где проблема? Зачем вы туда полезли смотреть? У вас что-то не работало? Если что-то не работало - то пишите, что именно.

Также: где в вашем вопросе написано, какую реализацию std::string вы использовали? Компилятор? Отладчик?

Внутреннее представление класса std::string зависит от реализации и может быть оптимизировано массой разных способов, особенно для коротких или пустых строк. Вполне возможно, что для такой - пустой - строки через этот указатель и не должно быть видно никаких осмысленных символов. Да, и я тоже вижу, что у меня в Visual Studio в таком примере поле ... _Bx -> _Ptr содержит мусор. Это нормально.

Возьмите строку подлиннее, и вы увидите, что, начиная с какой-то длины (16 символов?), начнет использоваться поле ... _Bx -> _Ptr.

Еще раз: где описание реальной проблемы, которую вы пытаетесь решить? Что не работает?

Цитата Сообщение от Skel Посмотреть сообщение
Глюк какой, что ли...
Не нужно строить фантастических теорий, когда вполне естественное и логичное объяснение лежит на поверхности.
0
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
27.03.2021, 06:29  [ТС] 4
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Зачем вы туда полезли смотреть? У вас что-то не работало?
Да, я потом использую эту переменную Name для проверки имени на соответствие. Пользователь вводит название песни, прога проверяет все альбомы на подходящие песни и возвращает первую найденную. В альбомах по 4 песни. Как работает цикл: пока имя песни не пустое значение, то проверяй ее на соответствие, иначе переходи к следующему альбому. В первом альбоме 4 песни он проверяет нормально, но как только доходит до следующей песни (которой по факту не существует, там должен мусор лежать), там лежит "ошибка чтения символов строки", и выдает исключение bad_alloc.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
содержит мусор. Это нормально.
Если бы просто мусор - то да, нормально. Но туда почему-то записывается именно ошибка. Код скину в след. посте, чтоб этот не нагромождать.

Добавлено через 6 минут
У меня еще есть класс Band (это сама группа, но она не так важна, там лишь метод сравнения песен лежит, который нужен).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Song
{
private:
    std::string Name;
    int Duration;
 
public:
    Song()
    {
        this->Name = "";
        this->Duration = 0;
    }
std::string GetSongName()
    {
        return this->Name;
    }
};
 
class Album
{
private:
    std::string Name;
    int ReleaseYear;
    Song* Songs;
 
public:
    Album()
    {
        this->Name = "";
        this->ReleaseYear = 1900;
        this->Songs = { };
    }
 
Song* GetAlbumSongs()
    {
        return this->Songs;
    }
};
 
class Band
{
private:
    std::string Name;
    std::string Description;
    Album* Albums;
 
public:
    Band()
    {
        this->Albums = {};
        this->Description = "";
        this->Name = "";
    }
Album* GetBandAlbums()
    {
        return this->Albums;
    }
 
Song* FindSong(std::string songTitle, int albCount)
    {
        int b = 0;
        int g = 0;
 
        for (int i = 0; i < albCount; ++i)
        {
            b = 0;
            while (this->GetBandAlbums()[i].GetAlbumSongs()[b].GetSongName() != "") // проверка, пока имя песни не пустое значение
            {
 
                if this->GetBandAlbums()[i].GetAlbumSongs()[b].GetSongName() == songTitle) // сравнение имени песни
                {
                    return this->GetBandAlbums()[i].GetAlbumSongs();
                }
                ++b;
 
            }
        }
 
        return nullptr;
    }
}
0
Вездепух
Эксперт CЭксперт С++
12641 / 6548 / 1758
Регистрация: 18.10.2014
Сообщений: 16,515
27.03.2021, 06:39 5
Цитата Сообщение от Skel Посмотреть сообщение
Если бы просто мусор - то да, нормально. Но туда почему-то записывается именно ошибка.
Вы делаете какие-то дикие и странные фантасмагорические выводы. С чего вы взяли, что туда "записывается именно ошибка"? Никакая "ошибка" туда не записывается.

Поле ... _Bx -> _Ptr в отладочном режиме содержит 0x6161616161616161 или 0xcdcdcdcdcdcdcd00, т.е. какое-то явно специально выбранное бессмысленно-мусорное указательное значение. А сообщение об "ошибке" вам пишет уже отладчик. Никуда это сообщение не "записывается".

Цитата Сообщение от Skel Посмотреть сообщение
и выдает исключение bad_alloc.
Никакого отношения к теме ... _Bx -> _Ptr эта ошибка не имеет. Вы накосячили где-то совсем в другом месте.
0
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
27.03.2021, 06:40  [ТС] 6
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Вы делаете какие-то дикие и странные фантасмагорические выводы
Однако прога перестала работать ни с того ни с сего. Пошел в отладчик и нашел такое. Раньше этого не было. Ничего я у класса песни не менял. Так ведь заметь, что в других классах с именами все в порядке, с песнями почему-то такое приключилось
0
Вездепух
Эксперт CЭксперт С++
12641 / 6548 / 1758
Регистрация: 18.10.2014
Сообщений: 16,515
27.03.2021, 06:50 7
Лучший ответ Сообщение было отмечено Skel как решение

Решение

Цитата Сообщение от Skel Посмотреть сообщение
Пошел в отладчик и нашел такое. Раньше этого не было.
Нет, вы выдумываете. Это было всегда. Это совершенно нормальное поведение std::string.

Цитата Сообщение от Skel Посмотреть сообщение
Однако прога перестала работать ни с того ни с сего.
Еще раз: никакого отношения к теме ... _Bx -> _Ptr ваше "перестала работать" не имеет. Вы накосячили где-то совсем в другом месте.

Перестаньте заниматься фигней и разглядывать ... _Bx -> _Ptr, а ищите у себя косяки: вылет за пределы массива, обращение к удаленной памяти и т.п.

Добавлено через 6 минут
Цитата Сообщение от Skel Посмотреть сообщение
В первом альбоме 4 песни он проверяет нормально, но как только доходит до следующей песни (которой по факту не существует, там должен мусор лежать)
Чего? Это что за белиберда? Какое еще "должен мусор лежать"?

Ваш цикл поиска песни написан так, что последовательность песен в альбоме обязательно (!) должна заканчиваться песней с пустым именем. Не "мусором", а песней с пустым именем (!). Если в альбоме 4 песни, то размер массива песен должен равняться 5 и последняя "фиктивная" песня должна иметь пустое имя. Если вы не соблюдете это жесткое правило, программа будет падать.
1
0 / 0 / 0
Регистрация: 23.08.2020
Сообщений: 19
27.03.2021, 07:13  [ТС] 8
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Возьмите строку подлиннее
Смотри, я в конструкторе изменил поле присвоения названия песни на 20-25 букв d, вместо "" (как ты и сказал, взять строку подлиннее). И заработало. Возвращаю обратно на пустое имя - ошибка. Как так-то? Неужели мне теперь по стандарту каждой песни какое-то имя из 15+ букв задавать? Некрасиво как-то.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Чего? Это что за белиберда?
Цикл безотказно работает. При встрече с мусором он его считает за пустую строку и просто переходит к след. альбому.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Если в альбоме 4 песни, то размер массива песен должен равняться 5 и последняя "фиктивная" песня должна иметь пустое имя
Зачем выделять место еще для одной лишней песни? Вот если б разговор про выделение памяти под символы, то да, выделять нужно на 1 больше заявленного размера для '\0'.
UPD. Хм, точно, выделил на 1 больше размер массива - все теперь работает и с пустым значением строки. Спасибо большое!
0
фрилансер
5802 / 5316 / 1093
Регистрация: 11.10.2019
Сообщений: 14,205
27.03.2021, 07:29 9
Skel, Вот ещё вариант с STL, смотри, насколько всё проще )) Не нужно три дня штурмовать форум, десять минут - и всё готово

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <vector>
#include <optional>
 
class Song
{
public:
    std::string Name;
    int Duration{};
};
 
class Album
{
public:    
    std::string Name;
    std::vector<Song> Songs;
    int ReleaseYear{1900};
};
 
class Band
{
public:    
    std::string Name;
    std::string Description;
    std::vector<Album> Albums;
 
    std::optional<Song> FindSong(const std::string_view songTitle)const
    {
        for(const auto& Album:Albums)
        {
            for(const auto& song:Album.Songs)
            {
                if(song.Name==songTitle)
                {
                    return song;
                }
            }
        }
 
        return {};
    }
};
 
int main()
{
    Song s;
    s.Name="Hello";
    
    Album a;
    a.Name="Fallen";
    a.Songs.push_back(s);
    
    Band b;
    b.Name="Evanescence";
    b.Albums.push_back(a);
    
    if(auto song=b.FindSong("Hello"))
    {
        std::cout<<"song name: "<<song->Name<<'\n';
    }
}
1
Вездепух
Эксперт CЭксперт С++
12641 / 6548 / 1758
Регистрация: 18.10.2014
Сообщений: 16,515
27.03.2021, 07:33 10
Цитата Сообщение от Skel Посмотреть сообщение
Цикл безотказно работает. При встрече с мусором он его считает за пустую строку и просто переходит к след. альбому.
Ым... Што????

При встрече с "мусором" происходит неопределенное поведение и ваша программа падает во все воронье горло. А то, что вам раньше казалось, что она не падала - это вы ее просто плохо тестировали.

Цитата Сообщение от Skel Посмотреть сообщение
Зачем выделять место еще для одной лишней песни?
Чтобы программа не падала. Вам нужно иметь возможность определить фактический размер массива, чтобы не вылетать за его пределы. А как вы это будете делать - ваше дело.

Разумнее/экономнее было бы хранить размер массива, как это делает std::vector, а не цеплять в конце массива дополнительную фиктивную песню с пустым именем. Но и так тоже можно. А еще разумнее было бы просто использовать std::vector.

Главное - если вы будете рассчитывать на ваше наивное "при встрече с мусором он его считает за пустую строку", то ваша программа будет просто падать.
1
27.03.2021, 07:33
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.03.2021, 07:33
Помогаю со студенческими работами здесь

Ошибка при создании объекта класса
Есть класс, создаю объект, выходит ошибка &quot;cannot allocate an object of abstract type 'Cat'&quot; Что...

Ошибка в работе класса при создании нового объекта
Здравствуйте. Есть код класса при котором всё работает прекрассно когда один экземпляр, а когда...

Ошибка при чтении символов строки
Ошибка при чтении key_text при вызове метода object_yes_no(), почему? //Создание класса...

Ошибка при чтении символов строки
Здравствуйте, уважаемые форумчане! Решил вспомнить программирование и написать программу, которая...

Ошибка при чтении символов строки
Здравствуйте, уважаемые программисты! Решил написать программу, которая бы определяла...

Ошибка при чтении символов строки
Как я понял, что ошибка из-за функции ChooseAnswer. При использовании return. Если в каждый Case...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru