Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.87
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
#1

Битовые утечки при записи данных на диск - C++

06.06.2016, 14:42. Просмотров 3269. Ответов 119
Метки нет (Все метки)

Доброго дня форумчане!
Сорри если оффтоп но... Пишу в консольке на C++ (MSVCE 2010) различные движки по расчетам и тут столкнулся с опасной проблемой.
При записи на диск искажаются данные на один бит, где то один раз на 109 - 1011 данных. Бит просто "теряется" (был 1 стал 0 или наоборот) , соответственно данные уже не верны, что приводит к нулю все проделанную работу.
Из исследованного:
Бит теряется при записи как в поток текстового значения переменных (типа fileout << a[i] << endl;)
Так и при записи в двоичном виде (типа fileout.write(reinterpret_cast<char*>(a),size*sizeof(a[0]));)
Замечено, что данные в памяти верные, т.к. были пойманы моменты при повторном выводе из того же массива все данные были записаны корректно.
Ошибка не зависит от винчестера на который данные были записаны (были записи на 3 различных винта, один из которых рейд массив).
Чаще всего теряется один из старших битов (типа 24-й бит в unsigned long или 24-й в unsigned long long). Других потерянных бит не замечено.
Термин "потерянный" возможно применяю в данном случае не верно. Т.к. заметно искажение только при его инвертировании. Соответственно если был сбой и он вместо 1 записал сбойную 1 - этого я не найду.
Система молчит про контроль целостности данных. Винт тоже. У винтов и рейда все показатели в порядке (блоки не сыпятся, SMART в порядке).

Сталкивался ли кто с подобным? В чем может быть проблема?

В ближайшем будущем хочу переустановить систему и MSVCE 2013. Но не уверен, что система виновата.
Кто что подскажет?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.06.2016, 14:42
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Битовые утечки при записи данных на диск (C++):

Избежать утечки памяти при преобразовании строки в массив символов - C++ Builder
Всем привет! Как избежать утечки памяти в таком коде: char* ConvertString(String input) { char *output = new char; ...

Утечки памяти при использовании new/delete для двумерных массивов - C++
Добрый день. Суть в том, что есть несколько функций, получающих на вход и возвращающих двумерные массивы. Реализация передачи массивов...

Битовые операции с разными типа данных - C++
Здравствуйте. В голове возник такой странный вопрос, а мб и не странный. Возможны ли битовые операции с разными типа данных, например int...

Битовые операции, битовые поля. - C++
Здравствуйте! Еслть 4 диапазона чисел: 0-100, 0-100, 0-6000, 0-3. Сделать в виде битовых операций. Записать в unsigned int. Использовать...

Ошибка при записи данных в файл - C++
Для записи перменной типа string выделяю динамически массив из 64 элементов char,после записи данных освобождаю память,но почему-то при...

Ошибка при записи в файл данных из обьекта класса - C++
#include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;fstream&gt; using namespace std; class Vector { public: double x; ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
08.06.2016, 14:12  [ТС] #16
Evg, разгоном процов не занимаюсь принципиально с 2000 года. Чуть завышенный показатель частоты - результат не совсем корректного определения частоты memtest-а. На старте показывает правильную частоту. Турбобуст в биосе отключен.
К сожалению мне не доступен подобный комп. Как то - объемы памяти и винтового пространства.
Цитата Сообщение от Evg Посмотреть сообщение
По описанию не исключаю ошибку процессора.
тестирую память каждым ядром проца поочередно.
Evg
Эксперт CАвтор FAQ
17634 / 5858 / 378
Регистрация: 30.03.2009
Сообщений: 16,156
Записей в блоге: 26
08.06.2016, 17:36 #17
Цитата Сообщение от Petrolion Посмотреть сообщение
тестирую память каждым ядром проца поочередно
Тестом для памяти ошибку процессора не найдёшь. Тем более теми, что на голой машине работают (без ОС), а потому такие тесты в принципе не создают условий для процессора, которые есть в нормальной жизни

Цитата Сообщение от Petrolion Посмотреть сообщение
К сожалению мне не доступен подобный комп
А зря попробовать очень надо. Сильное подозрение на ошибку аппаратуры. Т.е. если на полностью другом компе ошибка воспроизведётся, то скорее всего ошибка программная (не исключая ОС)

Добавлено через 2 минуты
Цитата Сообщение от Petrolion Посмотреть сообщение
Evg, разгоном процов не занимаюсь принципиально с 2000 года
Ошибка процессора не обязательно есть результат разгона. Может быть брак или ошибка в целой партии, может быть принципиальная ошибка конкретной модели. Просто разгон сильно увеличивает вероятность воспроизведения подобных ошибок. Про разгон спросил на всякий случай
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
08.06.2016, 17:48  [ТС] #18
Evg, в том то и дело, что если проблема в системе или компиляторе то выход очевидный. Переустановка всего или переход на следующую версию MSVCE.
Сейчас экспериментирую с отловом ячейки памяти с багом. Раз замечено что всегда это 24-й бит, то поймав очередной раз ошибку, буду знать ее адрес. И ее адрес в памяти. Можно будет вывести содержимое этой ячейки и попробовать с ним "поиграть" вручную. Код проги тот же с модификацией (выложу позже).
Если отлов 3 и более ошибок даст один и тот же адрес памяти, это уже можно сдвинуть в аппаратную часть. Если адреса разные - ближе к софту.
Renji
1904 / 1302 / 292
Регистрация: 05.06.2014
Сообщений: 3,734
08.06.2016, 18:44 #19
Цитата Сообщение от Petrolion Посмотреть сообщение
Если адреса разные - ближе к софту.
Адреса виртуальные, то есть, при разных запусках программы, могут отображаться на разные места физической памяти.
Кстати, к вопросу о виртуальности - а если своп отключить? Потому что возможна ведь и цепочка "данные отгрузились в своп, диск сбойнул, когда данные загружали обратно фигня вышла".
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
08.06.2016, 18:52  [ТС] #20
Renji, своп отключен. При достаточности памяти - тормоза с ним.
vxg
Модератор
3158 / 1960 / 219
Регистрация: 13.01.2012
Сообщений: 7,504
10.06.2016, 10:37 #21
Цитата Сообщение от Petrolion Посмотреть сообщение
тестовая прога (x64)
как запустить ее на 12 ч тест? могу прогнать ее на нескольких машинах и посмотреть на результат
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
10.06.2016, 11:52  [ТС] #22
vxg, Спасибо огромное. К сожалению делаю это вручную.
1 запуск и 10 выводов бинарника со сравнением сторонней программой (FC) с эталонным файлом.
Затем перезапуск и все по новой. Сейчас подумаю как можно ее сделать в автоматическом режиме.

За два дня отловил три ошибки в памяти. (Если результат изменен именно в памяти, можно вторым проходом делать проверку сразу по памяти, добавлю в код.) С измененным кодом увидел, что чаще именно в памяти хранится неверный результат (отличный именно в 24-м бите).
Адреса 8-байтовых ячеек:
Код
172DB2928 (16) = 0001 0111 0010 1101 1011 0010 1001 0010 1000 (2)
1729E9928 (16) = 0001 0111 0010 1001 1110 1001 1001 0010 1000 (2)
1875D8928 (16) = 0001 1000 0111 0101 1101 1000 1001 0010 1000 (2)
Немного напрягает совпадение последних 3-х значений адреса. Но по большому счету, в случае постоянной сбойной ячейки число совпадающих значений адреса должно быть больше. Кто уточнит? Там ведь страничная (блочная) адресация?
Сам измененный код:
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
#include <iostream>
#include <fstream>
 
using namespace std;
 
 
int main()
{
    int n = 1<<30;
    int k = 1<<24;
    int c = 1;
    int a = 0;
    ofstream fbin, ftxt;
    unsigned long long * b = new unsigned long long[n];
    for (int i = 0; i < n; i++)
        b[i]=k+i;
    cout << "Table ready." << endl << hex << "addres table: " << b << dec << endl;
    do
    {
        cout << endl << "Menu:" << endl << "1 - output binary (Data.dat)" << endl << "2 - output text (Data.txt)" << endl;
        cout << "3 - out data of cell (on screen)" << endl << "4 - put data to cell" << endl << "0 - Exit" << endl << "your choise: ";
        cin >> c;
        switch(c)
        {
        case 1:
            fbin.open("Data.dat",ios_base::binary);
            fbin.write(reinterpret_cast<char*>(b),n*sizeof(b[0]));
            fbin.close();
            break;
        case 2:
            ftxt.open("Data.txt");
            for (int i = 0; i < n; i++)
                ftxt << b[i] << endl;
            ftxt.close();
            break;
        case 3:
            cout << "Addres of cell: ";
            cin >> a;
            cout << hex << "Value must be: " << (k+a) << endl << "Value at addr " << a << " (" << (b+a) <<") is: " << b[a] << dec << endl;
            break;
        case 4:
            cout << "Addres of cell for modify: ";
            cin >> a;
            cout << "Old value: " << b[a] << endl << "Enter new value: ";
            cin >> b[a];
            break;
        }
        cout << "Done." << endl;
    } while (c != 0);
    cin.get();
return 0;
}
Toshkarik - Поможет ли ECC память - если результат операции помещаемый в нее изначально неверен? Возможно ли, что она так же сохранит неверный результат?
vxg
Модератор
3158 / 1960 / 219
Регистрация: 13.01.2012
Сообщений: 7,504
10.06.2016, 11:58 #23
Цитата Сообщение от Petrolion Посмотреть сообщение
Сейчас подумаю как можно ее сделать в автоматическом режиме
что мешает считывать и сравнивать любое количество раз (например пока не поймает ошибку) в коде аналогичном предложенному здесь Битовые утечки при записи данных на диск
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
10.06.2016, 12:10  [ТС] #24
vxg, Сейчас как раз этим занимаюсь. Но как уже сказал, если ошибки в памяти, то лучше исключить работу с файлами - медленная операция.

Добавлено через 1 минуту
Вселяет оптимизм, что проблема все же может быть в софте, т.к. по железу memtest ошибок не нашел.
Evg
Эксперт CАвтор FAQ
17634 / 5858 / 378
Регистрация: 30.03.2009
Сообщений: 16,156
Записей в блоге: 26
10.06.2016, 17:23 #25
Цитата Сообщение от Petrolion Посмотреть сообщение
т.к. по железу memtest ошибок не нашел
Ещё раз. mmtest НЕ способен находить ошибки процессора (или других узлов), он не для того разрабатывался
avgoor
885 / 520 / 112
Регистрация: 05.12.2015
Сообщений: 1,467
10.06.2016, 17:41 #26
Petrolion, Может быть и ошибка процессора. Я один раз натыкался на похожее. Попробуйте обновить биос/микрокод процессора.
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
10.06.2016, 23:15 #27
Evg, как мне кажется, если бы процессор сбоил, то проблемы были бы хуже. Как минимум, после сбоя, i бы не возращалась к нормальному состоянию.

Petrolion, я не знаю, как точно все устроено, но немного поразмыслил. Скорей всего у Вас битая память. Точнее 1 бит. 24-ый - потому что вы выбрали 64 битный тип данных, из-за выравнивания он всегда будет находится на этой позиции. ECC думаю помог бы в этой ситуации, так как сбой, скорей всего, происходит при записи в этот бит. Если у Вас больше 1 модуля, попробуйте протестировать каждый по отдельности. Если один, то попробуйте найти/купить/попросить другой модуль.

Добавлено через 2 минуты
Не исключаю, что проблема в контроллере памяти, который, с большой вероятностью, находится в процессоре. Тогда, как и предположил Evg, проблема в нём. Но вероятность очень маленькая.
Petrolion
24 / 24 / 7
Регистрация: 02.02.2016
Сообщений: 124
11.06.2016, 11:47  [ТС] #28
Обнаружил неприятное, но сильно понятнее не стало.
"Бесконечный" код для теста был:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <fstream>
#include <conio.h>
 
using namespace std;
 
 
int main()
{
    int n = 1<<30;
    int k = 3<<24;
    unsigned long long c = 0;
    char o;
    bool te = true;
    int a = 0;
    ofstream flog;
    flog.open("Test.log",ios_base::app);
    unsigned long long * b = new unsigned long long[n];
    cout << hex << "Array at addres (" << b << "). " << dec << endl;
    flog << hex << "Array at addres (" << b << "). " << dec << endl;
    while (te)
    {
        for (int i = 0; i < n; i++)     //Asc tab
            b[i]=k+i;
        cout << "Table asc ready. Read:" << hex;
        flog << "Table asc ready. Read:" << hex;
        for (int m = 0; m < 8; m++)
        {
            cout << m;
            flog << m;
            c = k;
            for (int i = 0; i < n; i++,c++)
                if (b[i] != c)
                {
                    cout << endl << "Error at adr(" << (b+i) <<"). Value: " << b[i] << " must be: " << c << endl;
                    flog << endl << "Error at adr(" << (b+i) <<"). Value: " << b[i] << " must be: " << c << endl;
                }
            if (_kbhit())
            {
                o = _getch();
                if (o == 27)
                {
                    cout << " Exit ? ";
                    o = _getche();
                    cout << endl;
                    if (o == 'y' || o == 'Y')
                        te = false;
                }
            }
        }
        cout << endl;
        flog << endl;
 
        for (int i = 0; i < n; i++)     //Clr tab
            b[i]=0;
        cout << "Table clear ready. Read:" << hex;
        flog << "Table clear ready. Read:" << hex;
        for (int m = 0; m < 8; m++)
        {
            cout << m;
            flog << m;
            for (int i = 0; i < n; i++)
                if (b[i] != 0)
                {
                    cout << endl << "Error at adr(" << (b+i) <<"). Value: " << b[i] << " must be: 0" << endl;
                    flog << endl << "Error at adr(" << (b+i) <<"). Value: " << b[i] << " must be: 0" << endl;
                }
            if (_kbhit())
            {
                o = _getch();
                if (o == 27)
                {
                    cout << " Exit ? ";
                    o = _getche();
                    cout << endl;
                    if (o == 'y' || o == 'Y')
                        te = false;
                }
            }
        }
        cout << endl;
        flog << endl;
 
        for (int i = 0; i < n; i++)
            b[i]=0xffffffffffffffff;
        cout << "Table bit ready. Read:" << hex;
        flog << "Table bit ready. Read:" << hex;
        for (int m = 0; m < 8; m++)
        {
            cout << m;
            flog << m;
            c = 0xffffffffffffffff;
            for (int i = 0; i < n; i++)
                if (b[i] != c)
                {
                    cout << endl << "Error at adr(" << (b+i) <<"). Value: " << b[i] << " must be: " << c << endl;
                    flog << endl << "Error at adr(" << (b+i) <<"). Value: " << b[i] << " must be: " << c << endl;
                }
            if (_kbhit())
            {
                o = _getch();
                if (o == 27)
                {
                    cout << " Exit ? ";
                    o = _getche();
                    cout << endl;
                    if (o == 'y' || o == 'Y')
                        te = false;
                }
            }
        }
        cout << endl;
        flog << endl;
    }
    flog.close();
    cin.get();
return 0;
}
Код
Заполнение массива восходящими значениями от определенной величины.
Проверка массива на соответствие заполненному (8-16 раз).
Очистка массивы нулями.
Проверка все ли нули (8-16 раз).
Заполнение массива всеми заполненными битами.
Проверка всех бит на наличие заполнения (8-16 раз).
и все по новой...
Выход по Esc затем y.
Лог пишется параллельно в файл.
Обнаружил что если при запуске ошибка возникла в памяти, то она есть уже при всех считываниях (разумеется). Но при этом заполнение этого же массива нулями не показывает наличие сбоя в памяти при заполнении. Так же ведет себя заполнение единицами. Но при втором круге - заполнение восходящими значениями, опять возникает ошибка там же либо в другой ячейке. И так все время.
Если же с самого начала тест на возрастающих значениях ошибок не показал, то он его не покажет и через несколько часов.
Т.е. есть закономерность при запуске. Теоретически действительно может быть одно из ядер процессора. Только как узнать какое именно? (кол-во я получить могу, но вот номер...)
И опять же не без НО. Но почему при заполнении нулями и единицами сбоев нет совсем. Должны быть если это проц.
В приложенном файле логи ошибочных и удачных запусков.
В первом - кол-во проходов 16 для int k = 1<<24;
Во втором проходов 8 для int k = 3<<24;
Evg 4 версия мемтеста уже работает с памятью каждым ядром процессора по отдельности (параллельно и последовательно). Т.е. получается, что в данном случае сбой не в памяти, а возможно, в процессоре или в софте при расчете. Тогда почему при том же расчете при проверке, не происходит сбоя в том же самом ядре? Мой результат теста показал, что если ошибка появилась, то она уже есть все время в пределах текущего запуска и массива.
vxg можешь попробовать этот код запустить? Или может мой готовый exe файл дать? (На случай если у меня C++ погнал)
Вложения
Тип файла: zip Logs.zip (1.5 Кб, 2 просмотров)
nonedark2008
906 / 645 / 133
Регистрация: 28.07.2012
Сообщений: 1,758
11.06.2016, 11:58 #29
Цитата Сообщение от Petrolion Посмотреть сообщение
кол-во я получить могу, но вот номер...
GetCurrentProcessorNumber
Somebody
2788 / 1602 / 145
Регистрация: 03.12.2007
Сообщений: 4,193
Завершенные тесты: 1
11.06.2016, 12:37 #30
Тогда сначала надо привязать поток к процессору (SetThreadAffinityMask), а то он может в любое время перелететь на другое.

Добавлено через 19 минут
Цитата Сообщение от Petrolion Посмотреть сообщение
если ошибка появилась, то она уже есть все время в пределах текущего запуска и массива.
Тогда как-нибудь бы или узнать физический адрес этого места или хотя бы перезагрузить эту страницу по другому адресу и посмотреть, как будет после этого. Как бы только это сделать простым способом?..
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.06.2016, 12:37
Привет! Вот еще темы с ответами:

Утечки при использовании порта завершения и соккетов - C++
Здравствуйте, уважаемые Гуру! Реализовываю сервер с использованием порта завершения. Всё работает, всё прекрасно. Одно меня смущает -...

ClientDataSet, Blob утечки памяти при записи в файл - Delphi
столкнулся с такой ситуацией, есть ClientdataSet в котором есть блоб поле, которое я записываю процедурой ниже: Procedure...

При записи файлов на диск, комптютер выдал ошибку, что данный диск не может дальше использоваться - Windows 7
При записи файлов на диск, через некоторое время мой комптютер выдал ошибку, что данный диск не может дальше использоваться(или что-то...

При закачке игры на жесткий диск пишет "Ошибка при записи на диск" - Жесткие диски
В системе 2 жестких диска. Так вот, при попытке установить на жесткий диск игры со стима пишет &quot;Ошибка при записи на диск&quot;, загрузка...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
11.06.2016, 12:37
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru